它们真的一样吗?今天,我遇到了这个问题。下面是立即窗口的转储:
?s
"Category"
?tvi.Header
"Category"
?s == tvi.Header
false
?s.Equals(tvi.Header)
true
?s == tvi.Header.ToString()
true
也就是s和tvi。标头包含“Category”,但==返回false, Equals()返回true。
S被定义为字符串tvi。Header实际上是WPF的TreeViewItem.Header。那么,为什么它们返回不同的结果呢?我一直认为它们在c#中是可以互换的。
有人能解释一下这是为什么吗?
两个差异:
Equals is polymorphic (i.e. it can be overridden, and the implementation used will depend on the execution-time type of the target object), whereas the implementation of == used is determined based on the compile-time types of the objects:
// Avoid getting confused by interning
object x = new StringBuilder("hello").ToString();
object y = new StringBuilder("hello").ToString();
if (x.Equals(y)) // Yes
// The compiler doesn't know to call ==(string, string) so it generates
// a reference comparision instead
if (x == y) // No
string xs = (string) x;
string ys = (string) y;
// Now *this* will call ==(string, string), comparing values appropriately
if (xs == ys) // Yes
Equals will throw an exception if you call it on null, == won't
string x = null;
string y = null;
if (x.Equals(y)) // NullReferenceException
if (x == y) // Yes
注意,使用object可以避免后者成为问题。等于:
if (object.Equals(x, y)) // Fine even if x or y is null
TreeViewItem的Header属性静态类型为object类型。
因此==的结果是false。你可以用下面这个简单的代码片段重现这个过程:
object s1 = "Hallo";
// don't use a string literal to avoid interning
string s2 = new string(new char[] { 'H', 'a', 'l', 'l', 'o' });
bool equals = s1 == s2; // equals is false
equals = string.Equals(s1, s2); // equals is true
c#有两个“等于”概念:equals和ReferenceEquals。对于您将遇到的大多数类,==操作符使用其中一个或另一个(或两者都使用),并且通常只在处理引用类型时测试ReferenceEquals(但字符串Class是c#已经知道如何测试值相等的实例)。
Equals比较值。(即使两个独立的int变量不存在于内存中的同一位置,它们仍然可以包含相同的值。)
ReferenceEquals比较引用并返回操作数是否指向内存中的同一对象。
示例代码:
var s1 = new StringBuilder("str");
var s2 = new StringBuilder("str");
StringBuilder sNull = null;
s1.Equals(s2); // True
object.ReferenceEquals(s1, s2); // False
s1 == s2 // True - it calls Equals within operator overload
s1 == sNull // False
object.ReferenceEquals(s1, sNull); // False
s1.Equals(sNull); // Nono! Explode (Exception)
两个差异:
Equals is polymorphic (i.e. it can be overridden, and the implementation used will depend on the execution-time type of the target object), whereas the implementation of == used is determined based on the compile-time types of the objects:
// Avoid getting confused by interning
object x = new StringBuilder("hello").ToString();
object y = new StringBuilder("hello").ToString();
if (x.Equals(y)) // Yes
// The compiler doesn't know to call ==(string, string) so it generates
// a reference comparision instead
if (x == y) // No
string xs = (string) x;
string ys = (string) y;
// Now *this* will call ==(string, string), comparing values appropriately
if (xs == ys) // Yes
Equals will throw an exception if you call it on null, == won't
string x = null;
string y = null;
if (x.Equals(y)) // NullReferenceException
if (x == y) // Yes
注意,使用object可以避免后者成为问题。等于:
if (object.Equals(x, y)) // Fine even if x or y is null
除了Jon Skeet的答案,我还想解释为什么大多数情况下,当使用==时,你实际上在不同的字符串实例上得到了具有相同值的答案:
string a = "Hell";
string b = "Hello";
a = a + "o";
Console.WriteLine(a == b);
如您所见,a和b必须是不同的字符串实例,但由于字符串是不可变的,因此运行时使用所谓的字符串实习来让a和b在内存中引用相同的字符串。对象的==操作符检查引用,由于a和b引用同一个实例,结果为真。当您更改其中任何一个时,将创建一个新的字符串实例,这就是为什么字符串实习是可能的。
顺便说一下,乔恩·斯基特的回答并不完整。的确,x == y是假的,但这只是因为他在比较对象,对象通过引用进行比较。如果你写(string)x == (string)y,它会再次返回true。字符串重载了它们的==-运算符,调用String。等于下面。