【问题标题】:Do I HAVE to override GetHashCode and Equals in new Classes?我必须在新类中覆盖 GetHashCode 和 Equals 吗?
【发布时间】:2009-03-04 00:38:58
【问题描述】:

好的,所以如果我重写 Equals,我需要重写 GetHashCode,反之亦然。

但我只是想知道:我是否应该在任何课程中始终覆盖这两个?特别是如果我知道我会在字典或类似的集合中使用它们?虽然这是fairly straight forward,但它仍然是每个班级的额外工作。

System.Object 实现是否糟糕到需要担心这个问题?

编辑:您能否详细说明一下什么是值和引用相等?因此,如果我有两个字符串(s1 和 s2)都是“测试”,它们的值相等,但由于它们是两个不同的字符串,它们不是引用相等的?好的,对于字符串来说这很简单,但是您希望引用或值相等的常见情况是什么?

【问题讨论】:

    标签: .net


    【解决方案1】:

    据我所知,只有在需要值相等语义时才需要覆盖它们。 System.Object 实现并不“坏”,它只是做一个引用检查(这是该级别的所有实现都可以做的)。

    简而言之:如果您需要某种基于值的相等性(基于类属性的相等性),那么可以,覆盖掉。否则,它应该已经很好了。

    编辑: 在上述情况下,您只需需要覆盖它们。如果你覆盖一个,你确实需要覆盖两者,原因很明显(它们需要保持一致等)。您可以出于其他答案中指出的其他原因(例如使用哈希值的算法的性能,即Dictionary 键等)在每个类上覆盖它们,但您不需要,默认的System.Object 实现将正常工作。

    编辑 2: 要求提供更多信息,所以这里。考虑以下伪类:

    public class User {
        private int _id;
        private string _username;
        public string Username { get {return _username;}};
        // [snip] Whatever other properties we might like to have.
    
        public User(string username) {
            // Initialise our user from a database, or whatever.
        }
    }
    

    就目前而言,以下代码可能看起来很直观:

    User foo = new User("me");
    User bar = new User("me");
    User baz = foo;
    
    if (foo.Equals(bar)) {
        Console.WriteLine("1: Success!");
    }
    if (foo.Equals(baz)) {
        Console.WriteLine("2: Success!");
    }
    

    但它只会打印出来:

    2:成功

    为什么? foobar 是该类的两个单独实例,并且具有单独的引用。引用就像 C/C++ 中的指针。 foo 和 baz 是相同的引用,因为一个是从另一个分配的。不过,它们都有相同的,用户称为“我”。基于值的.Equals 实现的示例实现可能是:

    partial class User {
        public override bool Equals(object b) {
            if (b == null) return false;
            if (b.GetType() != this.GetType()) return false;
    
            // Now the heavy lifting
            User other = (User)b;
            if (other._id == this._id) return true;
            else return false;
        }
    }
    

    看看它是如何检查类的部分属性以确定相等性的吗?这就是工作中的价值平等。引用相等只是一个简单的this == b 检查。

    【讨论】:

      【解决方案2】:

      这两种方法应该一致。换句话说,如果两个对象相等,那么每个对象都应该返回相同的哈希码。这在散列集合中尤为重要。为了在散列容器中找到与对象 X 匹配的对象,容器将只测试那些与 X 具有相同散列码的项目是否相等。

      【讨论】:

        【解决方案3】:

        仅当您需要值语义时。来自MSDN

        对于某些类型的对象,它是 希望有 Equals 测试 价值平等而不是参照 平等。这样的实现 如果两个对象相等,则返回 true 具有相同的值,即使它们是 不是同一个实例。定义 什么构成了一个对象的价值 取决于类型的实现者, 但它通常是部分或全部 存储在实例变量中的数据 的对象。例如,值 字符串的大小是基于字符的 字符串的;等式方法 String 类对任何返回 true 包含的字符串的两个实例 中的字符完全相同 相同的顺序。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多