( Приносим извинения за долгую настройку. Обещаю, здесь есть вопрос. )
Рассмотрим класс Узел
, который имеет неизменяемый уникальный идентификатор, который назначается во время создания. Этот идентификатор используется, помимо прочего, для сериализации при сохранении графа объекта. Например, когда объект десериализуется, он проверяется на соответствие с основным графом объектов по идентификатору, чтобы найти столкновение и отклонить его.
Кроме того, экземпляр Узел
создается только частной системой, и все публичные доступы к ним осуществляются через интерфейс INode
.
Итак, у нас есть что-то вроде этого общего шаблона:
interface INode
{
NodeID ID { get; }
// ... other awesome stuff
}
class Node : INode
{
readonly NodeID _id = NodeID.CreateNew();
NodeID INode.ID { get { return _id; } }
// ... implement other awesome stuff
public override bool Equals(object obj)
{
var node = obj as INode;
return ReferenceEquals(node, null) ? false : _id.Equals(node.ID);
}
public override int GetHashCode()
{
return _id.GetHashCode();
}
}
Мои вопросы касаются этих функций .NET, связанных со сравнением / равенством:
IEquatable
IComparable
/ IComparable
operator ==
/ operator! =
Наконец, вот вопросы. При реализации такого класса, как Узел
:
IEquatable
из INode
или узла
? Учитывая, что IEquatable
, похоже, используется (в основном в BCL) только через проверки типа во время выполнения, есть ли смысл или не расширять INode
? IEquatable
также является частью узла
? obj как NodeID
в Equals
? Проработав на C # более десяти лет, мне неловко не иметь полного понимания этих интерфейсов и передовых практик, связанных с ними.
(Обратите внимание, что наши системы .NET встроены в 95% C #, 5% C ++ / CLI, 0% VB (если это имеет значение).