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

时间:2016-07-13 11:36:17

标签: c# inheritance equals equality

考虑下面这段代码。

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

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

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

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

虽然以下代码输出两者:

object str = "test";
object str1 = "test";
Console.WriteLine(str==str1); // true
Console.WriteLine(str.Equals(str1)); // true

5 个答案:

答案 0 :(得分:33)

使用:

Console.WriteLine(str==str1); // false

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

使用:

Console.WriteLine(str.Equals(str1));  // true

您在object上调用 虚拟 方法。虚拟意味着它将在运行时转到与override相关的任何内容。类System.String具有覆盖功能,由于str将具有运行时类型System.String,因此“虚拟调度”将使用覆盖。

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

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

答案 1 :(得分:3)

当在类型为object的表达式上使用==时,它将解析为System.Object.ReferenceEquals。

Equals只是一个虚方法,并且表现如此,因此将使用被覆盖的版本(对于字符串类型,它将比较内容)。

答案 2 :(得分:2)

这是因为字符串实习;当你写:

object str = "test";
object str1 = "test";
Console.WriteLine(str==str1);

这可以正常工作,因为编译器在内部并静默地将两个字符串复制到一个位置,因此两个指针实际上将指向相同的对象

如果你从一个字符数组中创建一个字符串,编译器就不够聪明,无法理解你的意图,而且它与上面的内容相同,所以,作为一个字符串引用类型,它们& #39;有效地在内存中有两个不同的对象

看一下这篇文章:https://blogs.msdn.microsoft.com/ericlippert/2009/09/28/string-interning-and-string-empty/

等于方法在字符串中被覆盖,因此它将字符串的实际内容而非地址进行比较为 == ReferenceEquals )在您的情况下,因为类型是对象

答案 3 :(得分:1)

我认为这是因为String == operator仅将string类型作为参数,而.Equals method需要object 1}}类型作为参数。

由于字符串==仅将string类型作为参数,因此重载决策选择要用于比较的对象==运算符。

答案 4 :(得分:-3)

String.Equals方法的帮助将此作为注释:

  

此方法执行序数(区分大小写和   文化不敏感的比较。

因此,通过char检查字符串char来完成比较,从而得到true。