他们真的一样吗?今天,我遇到了这个问题.这是立即窗口的转储:
?s
"Category"
?tvi.Header
"Category"
?s == tvi.Header
false
?s.Equals(tvi.Header)
true
?s == tvi.Header.ToString()
true
Run Code Online (Sandbox Code Playgroud)
所以,无论是s和tvi.Header包含"类别",而是==返回false,并Equals()返回true.
s被定义为字符串,tvi.Header实际上是一个WPF TreeViewItem.Header.那么,他们为什么会回归不同的结果呢?我一直认为它们可以在C#中互换.
任何人都可以解释为什么会这样吗?
Jon*_*eet 342
两个区别:
Equals是多态的(即它可以被覆盖,并且使用的实现将取决于目标对象的执行时类型),而==used 的实现是基于对象的编译时类型确定的:
// 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
Run Code Online (Sandbox Code Playgroud)Equals 如果你在null上调用它将会爆炸,==不会
string x = null;
string y = null;
if (x.Equals(y)) // Bang
if (x == y) // Yes
Run Code Online (Sandbox Code Playgroud)请注意,使用以下方法可以避免后者出现问题object.Equals:
if (object.Equals(x, y)) // Fine even if x or y is null
Run Code Online (Sandbox Code Playgroud)
Jef*_*dge 61
问题中出现的明显矛盾是由于在一种情况下Equals在一个string对象上调用该函数,而在另一种情况下==是在该System.Object类型上调用该运算符.string并且object彼此不同地实现相等(分别为值与参考).
除此之外,任何类型都可以定义==和Equals不同,因此通常它们不可互换.
这是一个使用的例子double(来自Joseph Albahari的C#语言规范§7.9.2的注释):
double x = double.NaN;
Console.WriteLine (x == x); // False
Console.WriteLine (x != x); // True
Console.WriteLine (x.Equals(x)); // True
Run Code Online (Sandbox Code Playgroud)
他接着说,该double.Equals(double)方法旨在与列表和词典一起正常工作.该==运营商,在另一方面,被设计为遵循浮点类型的IEEE 754标准.
在确定字符串相等性的特定情况下,行业偏好既不使用==也不使用string.Equals(string)大部分时间.这些方法确定两个字符串是否是相同的字符,这很少是正确的行为.最好使用string.Equals(string, StringComparison),它允许您指定特定类型的比较.通过使用正确的比较,您可以避免很多潜在的(非常难以诊断)错误.
这是一个例子:
string one = "Caf\u00e9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE
string two = "Cafe\u0301"; // U+0301 COMBINING ACUTE ACCENT
Console.WriteLine(one == two); // False
Console.WriteLine(one.Equals(two)); // False
Console.WriteLine(one.Equals(two, StringComparison.InvariantCulture)); // True
Run Code Online (Sandbox Code Playgroud)
这个例子中的两个字符串看起来都一样("Café"),所以如果使用天真(序数)相等,这可能非常难以调试.
pal*_*wim 44
C#有两个"等于"的概念:Equals和ReferenceEquals.对于您将遇到的大多数类,==运算符使用一个或另一个(或两者),并且通常仅ReferenceEquals在处理引用类型时进行测试(但是stringClass是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)
Run Code Online (Sandbox Code Playgroud)
Dir*_*mar 16
静态类型的Header属性TreeViewItem是类型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
Run Code Online (Sandbox Code Playgroud)
除了Jon Skeet 的回答之外,我还想解释一下为什么大多数时候使用时==您实际上会在true具有相同值的不同字符串实例上获得答案:
string a = "Hell";
string b = "Hello";
a = a + "o";
Console.WriteLine(a == b);
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,a而且b必须是不同的字符串实例,但因为字符串是不可变的,运行时使用所谓的字符串实习,让双方a和b引用相同字符串在内存中。==对象的运算符检查引用,并且由于a和b引用同一个实例,结果是true。当您更改其中任何一个时,都会创建一个新的字符串实例,这就是可以使用字符串实习的原因。
顺便说一下,Jon Skeet 的回答并不完整。确实,x == y是false但那只是因为他正在比较对象和对象通过引用进行比较。如果你写(string)x == (string)y,它会true再次返回。所以字符串有它们的 == 运算符重载,它String.Equals在下面调用。
| 归档时间: |
|
| 查看次数: |
248484 次 |
| 最近记录: |