С# 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)
внутренне. По умолчанию он проверяет ссылочное равенство. Это происходит иначе, если статический оператор ==
был перегружен для типов в выражении, поскольку они объявлены во время компиляции.