== vs. Object.Equals(object) в .NET.

Итак, когда я был сравнительным новичком для новичков, я был прямо сейчас, я думал, что эти две вещи были синтаксическим сахаром друг для друга, то есть использование одного над другим было просто личным предпочтением. Со временем я пришел к выводу, что эти два не то же самое, даже в реализации по умолчанию (см. this и this). Чтобы еще больше смутить вопрос, каждый из них может быть переопределен/перегружен отдельно, чтобы иметь совершенно разные значения.

Это хорошая вещь, каковы различия, и когда/почему вы должны использовать один над другим?

Ответ 1

MSDN имеет четкое и четкое описание обеих вещей.

object.Equals method

operator ==

Перегружаемые операторы

Рекомендации по переопределению равных() и операторов ==

Это хорошо, что такое различия, и когда/почему вы должны использовать один над другим?

Как это может быть "хорошо" или "плохо"? Один - метод, другой - оператор. Если ссылочного равенства недостаточно, перегрузите их, иначе оставьте их как есть. Для примитивных типов они просто работают из коробки.

Ответ 2

string x = "hello";
string y = String.Copy(x);
string z = "hello";

Проверить, если x указывает на тот же объект, что и y:

(object)x == (object)y  // false
x.ReferenceEquals(y)    // false
x.ReferenceEquals(z)    // true (because x and z are both constants they
                        //       will point to the same location in memory)

Чтобы проверить, имеет ли x то же строковое значение, что и y:

x == y        // true
x == z        // true
x.Equals(y)   // true
y == "hello"  // true

Обратите внимание, что это отличается от Java. В Java оператор == не перегружен, поэтому распространенная ошибка в Java:

y == "hello"  // false (y is not the same object as "hello")

Для сравнения строк в Java необходимо всегда использовать .equals()

y.equals("hello")  // true

Ответ 3

Учитывая текущую инструкцию Microsoft о операторах равенства == и !=, вывод следующий: == должен просто быть синтаксическим сахаром для Object.Equals():

Убедитесь, что Object.Equals и операторы равенства имеют точно такую ​​же семантику

из http://msdn.microsoft.com/en-us/library/vstudio/7h9bszxx(v=vs.110).aspx

То, что они отличаются, а не просто сахаром, в ретроспективе, выглядит как ошибка в их дизайне.

Если вы хотите быть уверенным, что получаете сравнение ИДЕНТИФИКАЦИЯ (при сравнении ссылок), используйте вместо этого ReferenceEquals.

К сожалению, обработка == настолько противоречива, что я обычно избегаю этого при манипулировании чужими пользовательскими классами и просто использую менее читаемые Equals(a, b) или ReferenceEquals(a, b), в зависимости от того, какой смысл я хочу.

ИМХО, было бы лучше, если бы люди вообще не реализовали == и !=. Просто укажите .Net по умолчанию Equals и ! Equals и внесите в него Equals.

Если у кого-то разные рассуждения, я бы хотел это услышать.

(И да, это действительно сбивает с толку, учитывая, что Java существовала в первую очередь и использует == для обозначения ReferenceEquals. Но слишком поздно менять .Net вести себя таким образом. И у нас есть собственное выражение Microsoft этот эффект в приведенной выше ссылке.)

Ответ 4

Я собирался опубликовать это как комментарий к принятому ответу, но я думаю, что это заслуживает рассмотрения при определении того, какой маршрут принять.

dotnetfiddle: https://dotnetfiddle.net/gESLzO

Код скрипта:

    Object a = null;
    Object b = new Object();

    // Ex 1
    Console.WriteLine(a == b);
    // Ex 2
    Console.WriteLine(b == a);

    // Ex 3     
    Console.WriteLine(b.Equals(a));
    // Ex 4
    Console.WriteLine(a.Equals(b));

Первые 3 примера WriteLine будут работать, а четвертый - исключение. 1 и 2 используйте ==, который является статическим методом, который не требует создания экземпляра объекта.

Пример 3 работает, потому что b создается.

Пример 4 завершается с ошибкой, потому что a есть null, и поэтому метод не может быть вызван на нулевом объекте.

Поскольку я пытаюсь сделать код как можно более ленивым, я использую ==, особенно при работе со сценариями, где любой объект (или оба) может быть нулевым. Если бы я этого не сделал, мне пришлось бы выполнить нулевую проверку, прежде чем можно было бы вызвать .Equals().

Ответ 5

Мое понимание использования обоих было следующим: use == для концептуального равенства (в контексте, эти два аргумента означают одно и то же?) и .Equals для конкретного равенства (эти два аргумента на самом деле точны тот же объект?).

Изменить: связанная статья Кевина Шеффилда лучше справляется с объяснением ценности и равенства ссылок...

Ответ 6

Возможно, вы захотите использовать .Equals, поскольку кто-то может прийти позже и перегрузить их для вас.

Ответ 7

Два из наиболее часто используемых типов, String и Int32, реализуют оба оператора ==() и Equals() как значение равенства (вместо ссылочного равенства). Я думаю, что можно рассмотреть эти два определения примеров, поэтому мой вывод состоит в том, что оба имеют одинаковые значения. Если Microsoft указывает в противном случае, я думаю, что они намеренно вызывают путаницу.

Ответ 8

Оператор == и Equals() оба одинаковы, а мы сравниваем значения вместо ссылок. Вывод обоих параметров аналогичен приведенному ниже примеру.

Пример

    static void Main()
    {
        string x = " hello";
        string y = " hello";
        string z = string.Copy(x);
        if (x == y)
        {
            Console.WriteLine("== Operator");
        }
        if(x.Equals(y))
        {
            Console.WriteLine("Equals() Function Call");
        }
        if (x == z)
        {
            Console.WriteLine("== Operator while coping a string to another.");
        }
        if (x.Equals(y))
        {
            Console.WriteLine("Equals() Function Call while coping a string to another.");
        }
    }

Вывод:

  == Operator
  Equals() Function Call
  == Operator while coping a string to another.
  Equals() Function Call while coping a string to another.