Пожалуйста, объясните методику, используемую в этом коде для проверки равенства и идентичности объектов.

Пожалуйста, объясните методику, используемую в этом коде для проверки равенства и идентичности объектов.

Лучше, если вы можете предоставить мне любую веб-ссылку / книгу-ссылку для подробного обсуждения.

[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 было бы гораздо предпочтительнее, но опять-таки: код выглядит таким... замученным... что мне не хочется переоценивать намерения.

Другие вопросы по тегам