此代码段是从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
当主方法变更为
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
我无法捉摸为什么?
编辑:一旦你了解字符串实习以下问题不适用。
如何在泛型方法接收的参数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
,但处理空值等了。 对于不等式,这个处理空值,并且两个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
,因为编译器和运行时的设计是高效的处理字符串; 您使用的任何文字被“拘留”和相同的情况下使用,每次在你的AppDomain。 编译器 (而非运行时)也做了CONCAT如果可能的话-即
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串; “乔恩”(实习),“我的名字是”(实习),和“我的名字是乔恩” 两个不同的实例 。 因此==
返回true,并且引用相等返回false。 但价值相等( EqualityComparer<T>.Default
)仍然会返回true。
今天学到了新的东西。
我想乔恩说的一个问题,我试图回答。
当你建立一个使用串联的字符串,==将返回true,匹配值的2串,但他们不指向同一个参考(我想,应该是由于字符串实习。乔恩指出该字符串实习恒定或工程文字)。
在通用版本,它在调用object.ReferenceEquals(比==不同,在字符串的情况下,确实==值比较)。
其结果是,级联版本返回false而定(文本字符串)版本返回true。
编辑:我觉得乔恩必须围绕在一个更好的方式来解释这个:)
懒惰的我来说,我已经买了这本书,但还没有得到它开始。 :(
它无关,与一般的方法,但琴弦的实例
在主要的第一个版本,你有:
string name = "Jon";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
这产生4个字符串。 其中两个编译时间常数,即“乔恩”和初始化intro1何时intro2编译器不能说名字总是乔恩和解析值运行时使每个intro1和intro2的一个新的字符串“我的名字是”但是。
在第二个版本
string intro1 = "My name is Jon";
string intro2 = "My name is Jon";
你只有一个字符串,那是一个编译时间常数:“我的名字是乔恩”,你分配一个字符串都intro1和intro2,这就是为什么
AreReferencesEqual(intro1, intro2)
返回在第一种情况下虚假和真实在第二