Что должен возвращать GetHashCode, когда идентификатор объекта равен нулю?

Что из следующего является правильным / лучше, учитывая, что свойство identity может быть нулевым.

public override int GetHashCode()
{
    if (ID == null) {
        return base.GetHashCode();
    }
    return ID.GetHashCode();
}

ИЛИ ЖЕ

public override int GetHashCode()
{
    if (ID != null) {
        return ID.GetHashCode();
    }
     return 0;
}

Обновление 1: обновлен второй вариант.

Обновление 2: Ниже приведены реализации Equals:

public bool Equals(IContract other)
{
    if (other == null)
        return false;
    if (this.ID.Equals(other.ID)) {
        return true;
    }
    return false;
}

public override bool Equals(object obj)
{
    if (obj == null)
        return base.Equals(obj);
    if (!obj is IContract) {
        throw new InvalidCastException("The 'obj' argument is not an IContract object.");
    } else {
        return Equals((IContract)obj);
    }
}

И удостоверение личности string тип.

3 ответа

Решение

Это действительно зависит от того, что вы хотите, чтобы означало равенство - важно, чтобы два равных объекта возвращали один и тот же хэш-код. Что означает равенство, когда идентификатор равен нулю? В настоящее время ваш метод Equals должен возвращать значение true, если свойства идентификатора имеют одинаковое значение... но мы не знаем, что он делает, если идентификатор равен нулю.

Если вы действительно хотите поведение первой версии, я бы лично использовал:

return ID == null ? base.GetHashCode() : ID.GetHashCode();

РЕДАКТИРОВАТЬ: на основе вашего метода Equals, похоже, что вы могли бы сделать свой метод GetHashCode:

return ID == null ? 0 : ID.GetHashCode();

Обратите внимание, что ваш Equals(IContract other) Метод также может выглядеть так:

return other != null && object.Equals(this.ID, other.ID);

Ваша текущая реализация фактически выдаст исключение, если this.ID нулевой...

Кроме того, ваш Equals(object) метод неверен - вы не должны выдавать исключение, если вам передан неподходящий тип объекта, вы должны просто вернуть false... то же самое, если obj нулевой. Таким образом, вы можете просто использовать:

public override bool Equals(object obj)
{
    return Equals(obj as IContract);
}

Однако меня беспокоит равенство, основанное на интерфейсе. Обычно два класса разных типов не следует считать равными, даже если они реализуют одни и те же интерфейсы.

Вы можете просто return 0; вам нужно вернуть один и тот же HashCode для тех же значений, а ID.GetHashCode() часто не будет возвращать 0, поэтому такая функция Hash может быть вполне подходящей для любых нужд. Поскольку вы не объединяете никакие значения (например, ID и хеши имен), его довольно четкий идентификатор является определяющим источником HashCode, поэтому фиксированное значение 0 для нулевого идентификатора звучит разумно.

В противном случае может быть правдой, что весь ваш подход к переопределению GetHashCode только с учетом поля идентификатора неверен (и вам нужно объединить несколько полей, чтобы вычислить из них хеш)

После ваших правок я могу сказать, что во втором переопределении Equals слишком много кода, просто замените его на

public override bool Equals(object obj)
{
    return Equals(obj as Contract);
}

Ваше переопределение Equals(контракт IContract) мне кажется некорректным, потому что контрактом определяется только ID, а если IContract имеет больше полей, чем ID, это будет неправильным переопределением Equals.

PS: На самом деле, если IContract - это интерфейс, вам, вероятно, нужно заменить ваш IEquatable<IContract> к бетону IEquatable<ClassName> контракт, потому что это будет плохой дизайн, чтобы иметь возможность возвращать, что разные экземпляры классов, реализующие один и тот же интерфейс, равны, потому что равенство по определению требует проверки того, что объекты имеют одинаковый тип на первом этапе проверки на равенство (обычно примерно 99,9% случаев)

Возможно, вы хотите что-то вроде этого?

override int GetHashCode()
{
    if (ID != null)
        return ID.GetHashCode();

    return DBNull.Value.GetHashCode();
}

Важно, чтобы два объекта с нулевыми идентификаторами считались равными?

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