Где реализация по умолчанию для ==
op_Equality
для типов значений?
Нет значения по умолчанию ==
для типов значений. Попробуйте написать свой собственный тип значения
struct JustAnotherValueType
{
public readonly int Field;
public JustAnotherValueType(int f) { Field = f; }
}
Сделайте два значения x
и y
вашего типа. Попробуйте сказать x == y
с ними. Это не скомпилируется. Вы можете сказать
(object)x == (object)y
, но при этом выполняется бокс x
(назовем его боксом 1) и бокс y
(бокс 2), а затем выполняется сравнение ссылок для двух блоков. Следовательно, он всегда будет возвращать false. И поэтому это бесполезно, и именно поэтому перегрузка ==(object x, object y)
не выбирается автоматически при использовании ==
между двумя JustAnotherValueType
.
Так что же происходит с int
и float
? Вы можете сравнить их с ==
в C #, и у них нет метода op_Equality
?! Объяснение состоит в том, что эти перегрузки определяются Спецификацией языка C # . См. Разделы Операторы сравнения целых чисел и Операторы сравнения с плавающей точкой .
Таким образом, факт заключается в том, что, хотя эти операторы не существуют как члены структур .NET, Спецификация языка C # определяет их, и компилятор C # должен создать некоторый действительный IL для имитации их поведения.
Кстати, System.Object
тоже не имеет op_Equality
. Это тоже определяется только C #. См. Раздел Операторы равенства типов ссылок . Обратите внимание, что System.Object
имеет метод ReferenceEquals
, который компилятор может выбрать для преобразования этой перегрузки ==
в. Также обратите внимание, что этот раздел спецификации содержит ограничения, так что x == y
никогда не будет выполнять бокс на x
или y
.
А как насчет типов значений, таких как DateTime
, TimeSpan
и Guid
, которые не упомянуты в спецификации C #, но для которых разрешено использовать ==
? Ответ: у этих до есть член op_Equality
.
Заключение: Спецификация языка C # определяет множество ==
перегрузок, которые требуются для реализации C #, и некоторые из этих перегрузок включают int
и float
и object
.
Примечание: Метод виртуального экземпляра Equals(object)
определен в object
и унаследован всеми типами значений. Для структур, которые сами не переопределяют этот метод, используется override
в System.ValueType
. Сравнивает по значению. Так что с x
и y
, как указано выше, x.Equals(y)
будет работать нормально. Equals
- это метод виртуального экземпляра. С другой стороны, ==
- это static
«метод», для которого выполняется разрешение перегрузки на основе типов времени компиляции двух операндов (без «виртуальной отправки»).