Пожалуйста, объясните методику, используемую в этом коде для проверки равенства и идентичности объектов.
Пожалуйста, объясните методику, используемую в этом коде для проверки равенства и идентичности объектов.
Лучше, если вы можете предоставить мне любую веб-ссылку / книгу-ссылку для подробного обсуждения.
[Serializable]
public abstract class BusinessObject<T> : IBusinessObject where T : BusinessObject<T>
{
private int? requestedHashCode;
public virtual int ID { get; set; }
public virtual bool Equals(IBusinessObject other)
{
if (null == other || !GetType().IsInstanceOfType(other))
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
bool otherIsTransient = Equals(other.ID, default(T));
bool thisIsTransient = IsTransient();
if (otherIsTransient && thisIsTransient)
{
return ReferenceEquals(other, this);
}
return other.ID.Equals(ID);
}
protected bool IsTransient()
{
return Equals(ID, default(T));
}
public override bool Equals(object obj)
{
var that = obj as IBusinessObject;
return Equals(that);
}
public override int GetHashCode()
{
if (!requestedHashCode.HasValue)
{
requestedHashCode = IsTransient() ? base.GetHashCode() : ID.GetHashCode();
}
return requestedHashCode.Value;
}
}
Что такое временный объект?
2 ответа
- сначала проверяется,
other
является экземпляром того же типа, что и текущий объект. Если нет, они не равны - затем выполняется равенство ссылок, чтобы проверить,
other
и текущий объект - это один и тот же экземпляр. Если они, очевидно, они равны - Если оба
other
и текущий объект является временным (т.е. еще не сохранен), у них нет идентификатора, поэтому его нельзя сравнивать по идентификатору. Вместо этого они сравниваются по ссылке. (как отметил Марк Грэвелл в комментариях, тест, чтобы проверить, является ли объект временным, сломан; нет смысла сравнивать int с default(T)) - В конце концов, их идентификаторы сравниваются; объекты считаются равными, если они имеют одинаковый идентификатор
Я думаю, что код пытается сделать, это сказать "есть ли у него еще идентификатор", то есть "временный" объект может (если я правильно прочитал намерения кода) быть тем, который еще не сохранен в БД. Тогда равенство определяется как:
- если у него есть идентификатор, он совпадает? (даже для разных экземпляров одного типа)
- если у него нет идентификатора, это тот же экземпляр объекта (ссылка)
к сожалению, реализация выглядит полностью нарушенной, так как Equals(ID, default(T))
бессмысленно, когда T
это что-то совершенно другое (BusinessObject<T>
) - отсюда default(T)
всегда будет null
а также ID
никогда не будет null
(это не обнуляется). Так что ничто никогда не будет сообщать о переходных процессах.
Дополнительно этот код:
if (null == other || !GetType().IsInstanceOfType(other))
чрезвычайно неэффективно. Я подозреваю что-то, связанное с as
было бы гораздо предпочтительнее, но опять-таки: код выглядит таким... замученным... что мне не хочется переоценивать намерения.