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

时间:2011-02-22 12:34:16

标签: c# gethashcode iequatable

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

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

OR

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);
    }
}

ID为string类型。

3 个答案:

答案 0 :(得分:23)

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

如果您实际上想要第一个版本的行为,我个人会使用:

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);
}
但是,我关注基于接口的相等性。通常,即使实现相同的接口,也不应认为两类不同类型是相等的。

答案 1 :(得分:4)

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

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

编辑后我可以说第二个等于覆盖的代码太多,只需用

替换它
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%的情况下)

答案 2 :(得分:0)

也许你想要的是这样的东西?

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

    return DBNull.Value.GetHashCode();
}

重要的是,如果两个具有空ID的对象被认为是相等的吗?