它们真的一样吗?今天,我遇到了这个问题。下面是立即窗口的转储:

?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

其他回答

对象由OBJECT_ID定义,OBJECT_ID是唯一的。如果A和B是对象 A == B为真,那么它们是相同的对象,它们有相同的数据和方法,但是,这也是成立的:

A.object_id == b.object_id

如果 A = (B)为真,这意味着两个对象处于相同的状态,但这并不意味着A和B完全相同。

字符串是对象。

请注意==和Equals操作符是自反的、simetric的、tranzitive的,因此它们是等价关系(使用关系代数术语)。

这意味着: 如果A, B和C是对象,则:

(1) A == A总是正确的;A. equals (A)总是正确的(反身性)

(2)如果A == B那么B == A;如果A等于(B)那么B等于(A) (simetry)

(3)如果A == B且B == C,则A == C;如果a .等于(B), B.等于(C),则a .等于(C)(静止性)

另外,你可以注意到这也是真的:

(A == B) => (A = (B)),但反过来就不对了。

A B =>
0 0 1
0 1 1
1 0 0
1 1 1

Example of real life: Two Hamburgers of the same type have the same properties: they are objects of the Hamburger class, their properties are exactly the same, but they are different entities. If you buy these two Hamburgers and eat one, the other one won't be eaten. So, the difference between Equals and ==: You have hamburger1 and hamburger2. They are exactly in the same state (the same weight, the same temperature, the same taste), so hamburger1.Equals(hamburger2) is true. But hamburger1 == hamburger2 is false, because if the state of hamburger1 changes, the state of hamburger2 not necessarily change and vice versa.

如果你和一个朋友同时得到一个汉堡,这是你的和他的,那么你必须决定把汉堡分成两部分,因为你gethamburger () == friend. gethamburger()为真,如果这种情况发生:friend. eathamburger(),那么你的汉堡也会被吃掉。

我可以写关于Equals和==的其他细微差别,但我有点饿了,所以我得走了。

此致敬意 拉约什·阿帕德。

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函数是在字符串对象上调用的,而在另一种情况下==操作符是在系统上调用的。对象类型。字符串和对象实现相等的方式不同(分别是值和引用)。

除此之外,任何类型都可以以不同的方式定义==和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

他接着说,double. equals (double)方法被设计用来正确地处理列表和字典。另一方面,==运算符是按照IEEE 754浮点类型标准设计的。

在确定字符串相等的特定情况下,行业偏好在大多数情况下既不使用==也不使用string. equals (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

这个例子中的两个字符串看起来是一样的("Café"),所以如果使用naïve(序数)相等,调试起来可能会非常困难。

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

两个差异:

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