有几件事正在发生。首先,在这个例子中:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
您声称:
两者都是不同的对象引用。
由于string interning ,这不是真的。s1
并且s2
是对同一个对象的引用。C# 规范保证 - 从 C# 4 规范的第 2.4.4.5 节:
当根据字符串相等运算符(第 7.10.7 节)等效的两个或多个字符串文字出现在同一程序中时,这些字符串文字引用相同的字符串实例。
所以在这种特殊情况下,即使你打印了,你仍然会得到“真实” object.ReferenceEquals(s1, s2)
,或者如果你让它使用真实的参考身份比较==
:
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
但是,即使这些是对单独对象的引用,==
也会为. 重载是一个编译时决定 - 要使用的实现取决于操作数的编译时类型。例如:string
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a == b); // Uses string's implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
将其与object.Equals(object)
虚拟方法进行比较。碰巧,它也重载String
了这个方法,但重要的是它覆盖了它。因此,如果我们将代码更改为:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
...然后编译代码中的两个方法调用都将简单地为 to object.Equals(object)
,但由于多态性,它们仍将String
打印 True :将使用 in 的实现。
下面是对重载方法的调用:
string a = new string('x', 1);
string b = new string('x', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)