Object.Equals является виртуальным, но Object.operator == не использует его в C #? - PullRequest
5 голосов
/ 16 сентября 2010

Меня поразила странная "асимметрия" в 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-гуру, но 2-е утверждение не выполняется.

В Java я узнал, что == является синонимом для чего-то под названием Object.ReferenceEquals здесь. В C # я думал, что Object.operator == использует Object.Equals, который является виртуальным, поэтому он переопределяется в классе System.String.

Может кто-нибудь объяснить, почему 2-й assert терпит неудачу в C #? Какие из моих предположений плохи?

Ответы [ 2 ]

7 голосов
/ 16 сентября 2010

Оператор == не является синонимом, это оператор, который определен для разных типов.

Оператор == определен для строк, а затем он действительно использует метод Equals:

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

Однако в вашем коде вы не используете оператор для строк, вы используете его для объектов, так что вы получите оператор ==, определенный для объектов, который использует ReferenceEqualsчтобы сделать сравнение.

Какая перегрузка используемого оператора определяется во время компиляции, поэтому именно тип переменных, определяющих перегрузку, а не фактический тип объектов, на которые указывают переменные.

6 голосов
/ 16 сентября 2010

Операторы определены как статические методы, поэтому они не могут участвовать в полиморфизме.Таким образом, ваше второе утверждение использует определение == для object (поскольку ваши переменные объявлены как object), которое только проверяет равенство ссылок.Если бы переменные были объявлены как string, использовалась бы перегрузка == для string, и второе утверждение было бы успешным.

...