Подтвердить что ты не робот

Почему IEquatable T не делал контравариантным в T для С# 4.0?

IEquatable < Т > может быть объявлено контравариантным в T, поскольку он использует только T во входной позиции (или, что эквивалентно, U, являющийся подтипом T, должен подразумевать, что IEquatable <T> является [подтипом] IEquatable <U> ).

Итак, почему команда BCL не аннотировала его (для С# 4.0) с ключевым словом "in", как это было со многими другими универсальными интерфейсами (например, полностью аналогичными IComparable)?

4b9b3361

Ответ 1

Я думаю, что это в основном по философской причине, а не по техническому ограничению, поскольку вполне возможно просто аннотировать интерфейс. IEquatable<T> предназначен для сравнения объектов одного и того же типа для точного равенства. Экземпляр суперкласса обычно не считается равным экземпляру подкласса. Равенство в этом смысле также подразумевает равенство типов. Это немного отличается от IComparable<in T>. Может быть разумным определять относительный порядок сортировки для разных типов.

Чтобы процитировать страницу MSDN на IEquatable<T>:

Примечания для исполнителей:

Замените параметр типа интерфейса IEquatable<T> на тип, реализующий этот интерфейс.

Это предложение далее демонстрирует тот факт, что IEquatable<T> предназначен для работы между экземплярами одного конкретного типа.

Ответ 2

Наследуемые типы обычно не реализуют IEquatable<T>. Если IEquatable<T> включил метод GetHashCode(), можно было бы определить семантику IEquatable<T>, чтобы сказать, что элементы должны сравниваться равными при проверке как T. К сожалению, тот факт, что IEquatable<T> связан с одним и тем же хэш-кодом как Object.Equals, означает, что вообще IEquatable<T> должен реализовать по существу ту же семантику, что и Object.Equals.

Следовательно, если реализация IEquatable<BaseClass> делает в нем что-либо, кроме вызова Object.Equals, производный класс, который переопределяет Object.Equals и GetHashCode() и не выполняет повторное выполнение IEquatable<BaseClass>, будет в конечном итоге сломанным реализация этого интерфейса; реализация IEquatable<BaseClass>, которая просто вызывает Object.Equals, будет работать отлично, даже в этом сценарии, но не даст реального преимущества над классом, который не реализует IEquatable<T>.

Учитывая, что наследуемые классы не должны внедрять IEquatable<T>, в первую очередь, понятие ковариации не относится к надлежащим реализациям интерфейса.