当对象的标识符为空时,GetHashCode应该返回什么?

Die*_*kes 22 c# iequatable gethashcode

考虑到identity属性可以为null,以下哪项是正确/更好的.

public override int GetHashCode()
{
    if (ID == null) {
        return base.GetHashCode();
    }
    return ID.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)

要么

public override int GetHashCode()
{
    if (ID != null) {
        return ID.GetHashCode();
    }
     return 0;
}
Run Code Online (Sandbox Code Playgroud)

更新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);
    }
}
Run Code Online (Sandbox Code Playgroud)

ID是string类型.

Jon*_*eet 25

它实际上取决于你想要的平等意义 - 重要的是两个相等的对象返回相同的哈希码.当ID为空时,等式意味着什么?目前,如果ID属性具有相同的值,则Equals方法必须返回true ...但是如果ID为null,我们不知道它的作用.

如果你真的想要第一个版本的行为,我个人会使用:

return ID == null ? base.GetHashCode() : ID.GetHashCode();
Run Code Online (Sandbox Code Playgroud)

编辑:基于你的Equals方法,看起来你可以制作你的GetHashCode方法:

return ID == null ? 0 : ID.GetHashCode();
Run Code Online (Sandbox Code Playgroud)

请注意,您的Equals(IContract other)方法也可能如下所示:

return other != null && object.Equals(this.ID, other.ID);
Run Code Online (Sandbox Code Playgroud)

如果this.ID为null,您当前的实现将实际抛出异常...

此外,您的Equals(object)方法不正确 - 如果您传递了不适当的对象类型,则不应抛出异常,您应该返回false... ditto if objnull.所以你实际上可以使用:

public override bool Equals(object obj)
{
    return Equals(obj as IContract);
}
Run Code Online (Sandbox Code Playgroud)

但是,我关注基于接口的相等性.通常,即使实现相同的接口,也不应认为两类不同类型是相等的.

  • @Dienekes:嗯,你的Equals(对象)方法可以解决这个问题.如果你的意思是只与其他合同类进行比较,那么就这样说吧.如果你真的*想要IContract的相等,我建议改为创建一个`IEqualityComparer <IContract>`. (2认同)

Val*_*zub 5

您可以简单地return 0;,您需要为相同的值返回相同的 HashCode,并且 ID.GetHashCode() 不会经常返回 0,因此这样的 Hash 函数可以满足任何需求。由于您没有组合任何值(例如 ID 和 Name Hashes ),因此非常清晰的 ID 是 HashCode 的定义源,因此将 Null ID 固定为 0 听起来很合理。

否则,仅考虑 ID 字段的 GetHashCode 覆盖的整个方法可能是错误的(并且您需要组合多个字段来计算它们的哈希值)

编辑后,我可以说第二个 Equals 覆盖代码太多,只需将其替换为

public override bool Equals(object obj)
{
    return Equals(obj as Contract);
}
Run Code Online (Sandbox Code Playgroud)

您的 Equals(IContractcontract) 覆盖对我来说似乎有问题,因为定义合同的唯一内容是 ID,如果 IContract 的字段多于 ID,那么它将是一个错误的 Equals 覆盖。

PS:实际上,如果 IContract 是一个接口,您可能需要将其替换IEquatable<IContract>为具体的IEquatable<ClassName>合约,因为能够返回实现相同接口的不同类实例是相等的,因为根据定义相等性需要检查对象是否具有相同的设计,这将是糟糕的设计相等性检查第一阶段的相同类型(通常在 99.9% 的情况下)