5

我在 C# 中遇到了一个我不太了解的奇怪“不对称”。请参阅以下代码:

using System;
using System.Diagnostics;
namespace EqualsExperiment
{
    class Program
    {
        static void Main(string[] args)
        {
            object apple = "apple";
            object orange = string.Format("{0}{1}", "ap", "ple");
            Console.WriteLine("1");
            Debug.Assert(apple.Equals(orange));
            Console.WriteLine("2");
            Debug.Assert(apple == orange);
            Console.WriteLine("3");
        }
    }
}

对于所有 .NET 专家来说,这可能是显而易见的,但第二个断言失败了。

在 Java 中,我了解到 == 是这里称为 Object.ReferenceEquals 的同义词。在 C# 中,我认为 Object.operator== 使用 Object.Equals,它是虚拟的,因此在 System.String 类中被覆盖。

有人可以解释一下,为什么第二个断言在 C# 中失败?我的哪些假设是错误的?

4

2 回答 2

7

==运算符不是同义词,它是为不同类型定义的运算符。

==运算符是为字符串定义的,然后它确实使用了该Equals方法:

public static bool operator ==(string a, string b) {
  return Equals(a, b);
}

但是,在您的代码中,您不是在字符串上使用运算符,而是在对象上使用它,因此您得到的是==为对象定义的运算符,用于ReferenceEquals进行比较。

使用哪个运算符的重载是在编译时决定的,因此决定重载的是变量的类型,而不是变量指向的对象的实际类型。

于 2010-09-16T10:30:49.037 回答
6

运算符被定义为静态方法,因此它们不能参与多态性。所以你的第二个断言使用==for的定义object(因为你的变量被声明为object),它只测试引用相等。如果变量声明为string,则将使用==for 的重载string,并且第二个断言将成功。

于 2010-09-16T10:21:56.500 回答