С# System.Object.operator ==()

Я пытаюсь понять, как использовать System.Object.operator ==().

Моя эффективная книга С# и страница здесь (http://www.srtsolutions.com/just-what-is-the-default-equals-behavior-in-c-how-does-it-relate-to-gethashcode), говорит, что:

"System.Object.operator ==() вызовет a.Equals(b), чтобы определить, равны ли a и b".

Итак, с моим кодом:

   object a = 1;
   object b = 1;

   if(object.Equals(a, b))
   {
    // Will get here because it calls Int32.Equals(). I understand this.

   }

   if(a == b)
   {
    // I expected it to get here, but it doesn't.
   }

Я ожидал (a == b), чтобы вызвать Int32, переопределить Equals и сравнить значения таким же образом, что и static objet.Equals(). Что мне не хватает?

Изменить: возможно, я добавил, что я вижу, что (a == b) тестирует - он тестирует равенство ссылок. Я был брошен этой книгой, которая, по-видимому, предполагает, что она будет работать внутренне как объект static. Элементы (obect, object) будут.

Ответ 1

Я не уверен, почему книга скажет это; на самом деле неверно, что по умолчанию == вызывает Equals. Кроме того, object НЕ перегружает ==. Оператор == по умолчанию выполняет сравнение значения равенства для типов значений и сравнение ссылочного равенства для ссылочных типов. Опять же, он НЕ перегружен для object (это для string). Поэтому, сравнивая object a = 1 и object b = 1 с помощью оператора ==, вы выполняете сравнение эталонного равенства. Поскольку это разные экземпляры boxed int, они будут сравнивать по-другому.

При всем том, что смущает эта проблема, я рекомендую вам внимательно прочитать §7.10 и особенно в § 7.10.6 спецификации.

Подробнее о тонкостях бокса (или, почему это необходимо в первую очередь), я отсылаю вас к предыдущему сообщению по этому вопросу.

Ответ 2

Поскольку тип объекта не переопределяет ==, а == проверяет ссылочное равенство по умолчанию, сравниваются ссылки a и b, так как оба являются объектами. Если вы хотите сравнить значение равенства, вам нужно сначала распаковать ints.

Ответ 3

Когда два объекта тестируются на равенство, они тестируются, чтобы проверить, ссылаются ли они на один и тот же объект. (EDIT: это вообще правда, однако == может быть перегружен, чтобы обеспечить функциональность, которую вы получаете от a.equals)

So

object a = 1;  
object b = 1;

Они не указывают на одно и то же адресное пространство.

Однако, если вы сделали

object a = 1;
object b = a;

Затем они будут указывать на тот же адрес.

Для примера с реальной жизнью возьмите две разные квартиры в одном здании, они имеют ту же самую планировку, одну и ту же 1 спальню, ту же кухню, одну и ту же краску, все о них одинаково, за исключением того, что квартира a - № 101 и квартира b - # 102. В каком-то смысле они являются одинаковыми a.equals(b), но в другом смысле они совершенно разные a!= B.

Ответ 4

== реализация object проверяет идентификацию, а не равенство. У вас есть две переменные, которые указывают на два разных объекта, поэтому == возвращает false.

Ответ 5

Вы объявили a и b как объект, который является ссылочным типом, а не типом значения. Таким образом, при a==b вы сравниваете ссылки объектов (которые будут отличаться), а не значения.

Ответ 6

System.Object не перегружает ==, поэтому a == b просто проверяет ссылочное равенство (и возвращает false). Поскольку перегрузка оператора реализована как статический метод, это не virtual.

Object.Equals, с другой стороны, определяется следующим образом:

Стандартная реализация Equals поддерживает ссылочное равенство для ссылочных типов и побитовое равенство для типов значений. Ссылка равенство означает, что ссылки на объекты, которые сравниваются относятся к одному объекту. Поразрядное равенство означает, что сравниваемые объекты имеют одно и то же двоичное представление.

Так как a и b имеют одинаковое двоичное представление, Object.Equals(a, b) возвращает true.

Ответ 7

System.Object.operator ==() вызовет a.Equals(b), чтобы определить, равны ли a и b

Это просто неверно. Если бы это было так, вы бы a == b возвращали true, так как a.Equals(b) возвращает true. Equals - виртуальный метод, поэтому не имеет значения, что значения int вставляются в квадрат; если вы вызываете a.Equals, который компилируется в callvirt и используется vtable.

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