为什么比较两个字符串作为对象导致意外结果

Ehs*_*jad 14 c# inheritance equality equals

考虑以下代码.

object str = new string(new char[] { 't', 'e', 's', 't' });
object str1 = new string(new char[] { 't', 'e', 's', 't' });
Console.WriteLine(str==str1); // false
Console.WriteLine(str.Equals(str1));  // true
Run Code Online (Sandbox Code Playgroud)

我理解在这里工作的相等运算符,因为我们已经隐式地转换为对象,等于运算符检查两者的引用是否相等并返回false.

但我对第二个问题感到困惑,返回true看起来它正在调用String类型提供的Equals覆盖实现,并且如果它们相等则检查字符串的内容.

我的问题是它为什么不检查运算符的内容相等性,它们的实际类型是字符串而不是对象.对 ?

以下代码输出两者:

object str = "test";
object str1 = "test";
Console.WriteLine(str==str1); // true
Console.WriteLine(str.Equals(str1)); // true
Run Code Online (Sandbox Code Playgroud)

Jep*_*sen 33

附:

Console.WriteLine(str==str1); // false
Run Code Online (Sandbox Code Playgroud)

在编译时确定使用哪个C#预定义(正式)重载operator ==.由于strstr1声明object,operator ==(object, object)选择了重载.这是在编译时修复的.仅仅因为实际的运行时类型更具体,那就不会改变.如果要在运行时进行绑定,请Console.WriteLine((dynamic)str == (dynamic)str1); /* true */改用.

附:

Console.WriteLine(str.Equals(str1));  // true
Run Code Online (Sandbox Code Playgroud)

你打电话给虚拟方法object.虚拟意味着它将override在运行时转到任何相关的东西.该类System.String具有覆盖,并且由于str将具有运行时类型System.String,因此"虚拟调度"将使用覆盖.


关于问题底部的补充:由于字符串实习,这种情况不同.字符串实习是一种优化,其中相同的物理实例用于其值相同的形式上不同的字符串.当您有两个字符串,其值在源代码中给出时,字符串实习将"优化"并对同一实例进行两次引用.这通常是无害的,因为字符串保证是不可变的.因此,通常您不关心它是相同的实例还是具有相同值的另一个实例.但在你的例子中,我们可以"揭示"实习生.

注意:字符串实习与您的原始问题无关.只有在您的问题中添加了新示例后,字符串实习才变得相关.