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

?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#中是可以互换的。

有人能解释一下这是为什么吗?


当前回答

很明显,tvi。header不是一个字符串。==是一个由String类重载的操作符,这意味着只有当编译器知道操作符的两端都是String时,它才会工作。

其他回答

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)

除了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。等于下面。

对象由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和==的其他细微差别,但我有点饿了,所以我得走了。

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

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

很明显,tvi。header不是一个字符串。==是一个由String类重载的操作符,这意味着只有当编译器知道操作符的两端都是String时,它才会工作。