abh*_*ash 6 .net c# generics string-interning
此代码段来自深度中的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));
}
Run Code Online (Sandbox Code Playgroud)
上面代码片段的输出是
True
False
Run Code Online (Sandbox Code Playgroud)
当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));
}
Run Code Online (Sandbox Code Playgroud)
上面代码片段的输出是
True
True
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么?
编辑:一旦你理解字符串实习以下问题不适用.
如何AreReferencesEqual在第二个代码片段中的Generic方法中接收参数?
连接时字符串类型有什么变化,以使==运算符不调用String类型的重载Equals方法?
Mar*_*ell 13
对于字符串的情况,您可能不打算使用引用相等性.要获得通用方法中的平等和不平等,最好的办法是:
EqualityComparer<T>.Default.Equals(x,y); // for equality
Comparer<T>.Default.Compare(x,y); // for inequality
Run Code Online (Sandbox Code Playgroud)
即
static bool AreValuesEqual<T>(T first, T second)
where T : class
{
return EqualityComparer<T>.Default.Equals(first,second);
}
Run Code Online (Sandbox Code Playgroud)
这仍然使用重载Equals,但也处理空值等.对于不等式,它处理空值,以及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));
Run Code Online (Sandbox Code Playgroud)
你得到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));
Run Code Online (Sandbox Code Playgroud)
是完全相同的代码与前面的例子.完全没有区别.但是,如果强制它在运行时连接字符串,它会假定它们可能是短暂的,因此它们不会被实习/重用.所以在这种情况下:
string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2));
Run Code Online (Sandbox Code Playgroud)
你有4个字符串; "Jon"(实习),"我的名字是"(实习),以及"我的名字是Jon"的两个不同实例.因此==返回true,引用相等返回false.但是value-equality(EqualityComparer<T>.Default)仍然会返回true.
今天学到了新东西.
我想Jon在其中一个问题中说过,我试着回答.
使用连接构建字符串时,==将为2个匹配值字符串返回true,但它们不指向相同的引用(我认为,它应该由于字符串内部.Jon指出字符串实习适用于常量或文字).
在通用版本中,它调用object.ReferenceEquals(与==不同.在字符串的情况下,==进行值比较).
因此,连接版本返回false,而常量(文字字符串)版本返回true.
编辑:我认为乔恩必须以更好的方式来解释这个问题:)
懒惰我,我已经买了这本书但尚未开始使用它.:(
| 归档时间: |
|
| 查看次数: |
985 次 |
| 最近记录: |