【问题标题】:Overriding GetHashCode [duplicate]覆盖 GetHashCode [重复]
【发布时间】:2011-05-13 12:46:30
【问题描述】:

如您所知,GetHashCode 返回一个半唯一值,可用于标识集合中的对象实例。作为一种好的做法,建议重写此方法并实现您自己的方法。

我的问题是 - 您在处理自定义对象时会覆盖此方法吗?如果是这样,您使用什么算法来生成唯一 ID?

我正在考虑生成一个 GUID,然后从该标识符获取整数数据。

【问题讨论】:

  • 阅读this question 及其答案。它概述了一个好的哈希码实现。对于可变对象 here 覆盖 GetHashCode 也有很好的讨论。
  • 我不知道“半唯一”是什么意思......一个值要么是唯一的,要么不是,而且哈希码不是唯一的。因此,它不允许您识别列表中的对象。覆盖GetHashCode 不是“一个好习惯”,这是您需要 时要做的事情(例如,将对象用作字典中的键),而不是因为您认为这是一个好习惯练习。
  • 使用对象作为键可以被认为是识别集合中的对象——这正是我寻找关于什么是构建标识符的最佳算法的输入的原因。截至半唯一 ID:west-wind.com/Weblog/posts/4741.aspx
  • 丹尼斯,你首先需要考虑你想要什么样的平等行为。对于默认的引用相等(对于具有标识的可变对象),您无需执行任何操作。

标签: c# algorithm methods overriding gethashcode


【解决方案1】:

如果您使用 resharper,它可以为您生成 GetHashCode()、Equals 和运算符方法体。

Alt+Insert 访问此菜单。

http://www.jetbrains.com/resharper/webhelp/Code_Generation__Equality_Members.html

【讨论】:

    【解决方案2】:

    当您覆盖GetHashCode() 时,您还需要覆盖Equals()operator==operator!=。并且要非常小心地满足这些方法的所有要求。

    指南是here on MSDN。最重要的一句话:

    在可变类型中覆盖 operator == 不是一个好主意。

    【讨论】:

    • 据我了解,这没有任何意义,因为对象不会改变它的状态。
    • 什么没有意义?
    • 字符串是不可变的,你没用过name == "x" 吗?
    • 是的,但是当你修改一个字符串时,你会创建一个新对象(例如当你使用替换时)。
    • 关键是,在重新分配变量之前,依靠 == 保持真实是很自然的;让突变副作用改变 == 过去的含义并不直观,因为默认情况下支持比较运算符的任何东西都是值类型或不可变的。这些仅在您说 var = "new value" 时才更改值,这明确暗示先前的 == 可能不再正确。引用类型可以从其他代码中改变状态,而在其他地方改变对象的方法可以改变相等性。 Equals 不提供相同的期望,因为它是一个方法定义,而不是语法。
    【解决方案3】:

    在我个人的使用中,我也只在覆盖 equals 方法时覆盖。通常,我会为我知道可能会对其运行 LINQ to Objects 查询或其他一些比较操作的对象执行此操作。

    如果说 LINQ to SQL 实体或 DTO 对象,我通常会返回主键值。无论返回什么,如果不将值存储在本地,可能会产生意想不到的结果。

    HTH。

    【讨论】:

      【解决方案4】:

      我通常会覆盖数据类(即值语义有意义的类)的哈希码和相等检查方法。查看this question 以获得常见的实现。如果您确实覆盖哈希码覆盖等于。使用 GUID 是一个非常糟糕的主意,因为您希望两个不同实例但具有相同 的对象具有相同的哈希码,并且等于返回 true。

      【讨论】:

        【解决方案5】:

        您只需要在覆盖 Equals 时覆盖 GetHashCode。默认的 GetHashCode 由运行时以您想要的类似方式实现 - 每个对象都有一个由运行时分配的隐藏字段。

        How to override GetHashCode

        实际上,您的 IDE 应该为您执行此操作 - 当您键入“override GetHashCode”时,IDE 应该生成此样板代码。 Visual Studio 不这样做,但 SharpDevelop 会。

        【讨论】:

        【解决方案6】:

        通常我使用类的组件属性中聚合的 GetHashCode。例如

        public class Test
        {
          public string Text { get; set; }
          public int Age { get; set; }
        
          public override GetHashCode()
          {
            int result = 
              string.IsNullOrEmpty(Text) ? 0 : Text.GetHashCode()
              + Age.GetHashCode();
        
            return result;
          }
        }
        

        【讨论】:

        • 这不是一个很好的方法,请参阅stackoverflow.com/questions/263400/…
        • 一般来说,添加不利于创建复合哈希码。但在这个具体的例子中,我认为它没有问题。但当然,不覆盖 Equals 的覆盖 GetHashCode 没有多大意义。
        • 嗯,你每天都能学到一些东西!
        猜你喜欢
        • 2012-07-13
        • 2012-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-16
        相关资源
        最近更新 更多