Object.Equals является виртуальным, но Object.operator== не использует его в C#?
Меня поразила странная "асимметрия" в 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 ответа
==
оператор не является синонимом, это оператор, который определен для разных типов.
==
оператор определен для строк, а затем он действительно использует Equals
метод:
public static bool operator ==(string a, string b) {
return Equals(a, b);
}
Однако, в вашем коде вы не используете оператор для строк, вы используете его для объектов, так что вы получите ==
оператор, определенный для объектов, который использует ReferenceEquals
сделать сравнение.
Какая перегрузка используемого оператора определяется во время компиляции, поэтому перегрузку определяет тип переменных, а не фактический тип объектов, на которые указывают переменные.
Операторы определяются как статические методы, поэтому они не могут участвовать в полиморфизме. Таким образом, ваш второй утверждение использует определение ==
за object
(поскольку ваши переменные объявлены как object
), который проверяет только ссылочное равенство. Если переменные были объявлены как string
, ==
перегрузка для string
был бы использован, и второй утверждал бы успешно.