Должен ли IEquatable <T>, IComparable <T> быть реализован на незакрытых классах?
У любого есть мнение о том,IEquatable<T>
или жеIComparable<T>
как правило, требует, чтобыT
являетсяsealed
(если этоclass
)?
Этот вопрос возник у меня, так как я пишу набор базовых классов, предназначенных для помощи в реализации неизменяемых классов. Частью функциональности, которую должен обеспечить базовый класс, является автоматическая реализация сравнений на равенство (используя поля класса вместе с атрибутами, которые можно применять к полям для управления сравнениями на равенство). Это должно быть очень приятно, когда я закончу - я использую деревья выражений для динамического создания скомпилированной функции сравнения для каждогоT
, поэтому функция сравнения должна быть очень близка к производительности обычной функции сравнения на равенство. (Я использую неизменный словарьSystem.Type
и двойная проверка блокировки, чтобы сохранить сгенерированные функции сравнения способом, который является достаточно эффективным)
Однако возникла одна вещь: какие функции использовать для проверки равенства полей-членов. Моим первоначальным намерением было проверить, является ли тип каждого члена поля (который я назовуX
) реализуетIEquatable<X>
, Однако, после некоторых размышлений, я не думаю, что это безопасно использовать, еслиX
являетсяsealed
, Причина в том, что еслиX
не являетсяsealed
Я не могу знать наверняка, еслиX
надлежащим образом делегирует проверки на равенство виртуальному методу наX
тем самым позволяя подтипу переопределять сравнение на равенство.
Затем возникает более общий вопрос - если тип не запечатан, должен ли он действительно реализовывать эти интерфейсы ВСЕ? Я бы подумал, что нет, так как я бы сказал, что контракт интерфейсов заключается в сравнении двухX
типы, а не два типа, которые могут или не могут бытьX
(хотя они, конечно, должны бытьX
или подтип).
Что вы ребята думаете? ДолженIEquatable<T>
а такжеIComparable<T>
Избегать открытых классов? (Также заставляет меня задуматься, есть ли для этого правило fxcop)
Моя текущая мысль - использовать только сгенерированную функцию сравненияIEquatable<T>
на членских полях, чьиT
являетсяsealed
и вместо того, чтобы использовать виртуальныйObject.Equals(Object obj)
еслиT
распечатывается, даже еслиT
инвентарьIEquatable<T>
, так как поле может потенциально хранить подтипыT
и я сомневаюсь, что большинство реализацийIEquatable<T>
разработаны соответствующим образом для наследования.