[英]Operator overloading in Generic Methods
此代码段来自深度中的C#
static bool AreReferencesEqual<T>(T first, T second)
where T : class
{
return first == second;
}
static void Main()
{
string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
}
上面代码片段的输出是
True
False
当main方法改为
static void Main()
{
string intro1 = "My name is Jon";
string intro2 = "My name is Jon";
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
}
上面代码片段的输出是
True
True
我无法理解为什么?
编辑:一旦你理解字符串实习以下问题不适用。
如何在第二个代码片段中的Generic方法
AreReferencesEqual
中接收参数?
连接时字符串类型有什么变化,以使==运算符不调用String类型的重载Equals方法?
对于字符串的情况,您可能不打算使用引用相等性。 要获得通用方法中的平等和不平等,最好的办法是:
EqualityComparer<T>.Default.Equals(x,y); // for equality
Comparer<T>.Default.Compare(x,y); // for inequality
即
static bool AreValuesEqual<T>(T first, T second)
where T : class
{
return EqualityComparer<T>.Default.Equals(first,second);
}
这仍然使用重载的Equals
,但也处理nulls等。 对于不等式,它处理空值,以及IComparable<T>
和IComparable
。
对于其他运营商,请参阅MiscUtil 。
重新提出问题; 如果是:
string intro1 = "My name is Jon";
string intro2 = "My name is Jon";
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
你得到true
, true
,因为编译器和运行时的设计是高效的处理字符串; 您使用的任何文字都是“interned”,并且每次在AppDomain中都使用相同的实例。 如果可能的话, 编译器 (而不是运行时)也会执行连接 - 即
string intro1 = "My name is " + "Jon";
string intro2 = "My name is " + "Jon";
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
与前一个示例完全相同 。 完全没有区别。 但是,如果强制它在运行时连接字符串,它会假定它们可能是短暂的,因此它们不会被实习/重用。 所以在这种情况下:
string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
你有4个字符串; “Jon”(实习),“我的名字是”(实习),以及“我的名字是Jon”的两个不同实例 。 因此==
返回true,引用相等返回false。 但是值相等( EqualityComparer<T>.Default
)仍然会返回true。
今天学到了新东西。
我想Jon在其中一个问题中说过,我试着回答。
使用连接构建字符串时,==将为2个匹配值字符串返回true,但它们不指向相同的引用(我认为,它应该由于字符串内部。Jon指出字符串实习适用于常量或文字)。
在通用版本中,它调用object.ReferenceEquals(与==不同。在字符串的情况下,==进行值比较)。
因此,连接版本返回false,而常量(文字字符串)版本返回true。
编辑:我认为乔恩必须以更好的方式解释这个:)
懒惰我,我已经买了这本书,但尚未开始使用它。 :(
它与泛型方法无关,而是与字符串的实例化无关
在主要的第一个版本中你有:
string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
这会创建4个字符串。 其中两个是编译时常量,即“Jon”和“My name is”但是在初始化intro1和intro2时,编译器不能说该名称始终为jon并且解析值运行时为每个intro1和intro2创建一个新字符串。
在第二个版本
string intro1 = "My name is Jon";
string intro2 = "My name is Jon";
你只有一个字符串,这是一个编译时间常量:“我的名字是Jon”,你将该字符串分配给intro1和intro2,这就是为什么
AreReferencesEqual(intro1, intro2)
在第一种情况下返回false,在第二种情况下返回true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.