【问题标题】:Why GetHashCode is not a property like HashCode in .NET为什么 GetHashCode 不是 .NET 中的 HashCode 之类的属性
【发布时间】:2009-02-11 20:49:27
【问题描述】:

为什么 GetHashCode 不是 .NET 中的 HashCode 之类的属性?

【问题讨论】:

    标签: c# .net hashcode


    【解决方案1】:

    可能是因为它需要计算,并且将其作为属性公开可能意味着哈希码已经免费提供。

    编辑: 相关指南:Properties versus Methods

    “该操作的成本很高,以至于您希望与用户沟通,他们应该考虑缓存结果。”

    也许 GetHashCode 在某些情况下已经足够昂贵了。

    【讨论】:

    • 谢谢,是否有没有需要计算的属性的指南?我问的原因是,当您访问该属性时,我看到了很多计算。
    【解决方案2】:

    我认为没有任何充分的理由。 GetHashCode 的任何实现都应该足够快以放入属性中。也就是说,.Net 框架中有plenty of design flaws,有些小,有些严重。这个好像很小。

    【讨论】:

      【解决方案3】:

      通常不可能为一个类定义一个 HashCode,因为:

      例如类的对象不 有一个明确的概念 身份。

      因此,通常使 GetHashCode() 方法抛出 NotImplementedException。如果 HashCode 是一个属性,这当然会出现各种问题,因为大多数人(和调试器)认为获取属性的值总是有效的

      【讨论】:

      • 几乎所有类对象通常都应该具有引用语义或不可变值语义。具有引用语义的对象具有明确的标识概念(当且仅当 X 和 Y 引用同一个对象时,对象 X 和对象 Y 相等)。具有不可变值语义的对象具有明确的标识概念(如果对象 X 和对象 Y 具有相等的值,则它们是相等的)。哪些类型的对象没有明确定义的身份概念?
      • @supercat,Equals 应该只为具有相同 HashCode 的对象返回 true,但是我经常看到一个 equals 方法定义只是为了在不可变的对象上使用单元测试。因此,要停止来自编译器的警告,必须重写 GetHashCode(),但要知道该对象永远不应该用作键。如果对象上没有有用的 equals 方法,nUnit 中集合上的资产将不起作用。
      • 这绝对是对 Object.Equals() 的滥用。实际上,我希望该方法被命名为 Equivalent(),而不是 Equals(),因为它是等价的概念,而不是普遍适用的名称,并且在某些情况下,它可能对某些对象有用具有更宽松语义的 Equals() 方法。例如,如果我有我的 druthers,Equivalent(1.00m, 1.0m) 会是假的,但 Equals(1.00m, 1.0m) 会是真的。 Equals 将由规范定义为临时属性,与 Equivalent 不同(只要正确实现)是不可变的。
      【解决方案4】:

      除了一个属性只是一个getter和一个setter方法之外,从设计的角度来看,一个属性不应该包含除了初始化或验证之外的任何计算,例如:

      private object _obj;
      public object Obj
      {
        get
        {
          if(_obj == null)
          {
            _obj = new object();
          }
          return _obj;
        }
        set
        {
          if(value == badvalue)
          {
            throw new ArgumentException("value");
          }
          _obj = value;
        }
      }
      

      GetHashCode() 不包含大量计算,但它可以包含如此长时间运行的操作(只是因为它可以以复杂的方式计算对象的哈希码),这就是为什么它是一个方法而不是一个属性.

      【讨论】:

        【解决方案5】:

        只有在它们背后的计算非常快或缓存时才应该使用属性

        除了大多数时候,属性中唯一的逻辑应该是验证

        【讨论】:

          【解决方案6】:

          您必须记住,.NET Framework 旨在支持多种语言。

          理论上,您可以创建一个无法正确覆盖属性的编译器。虽然这会产生一个非常糟糕的编译器,但它不一定是非法的。 (记住属性只是带有一些元数据的方法)

          【讨论】:

          • 你也可以制作一个不能覆盖方法的编译器。许多其他 .NET 接口需要覆盖属性。
          • 很多接口都需要重写一个属性,但是 Object 是一切的祖父,为什么不保持简单呢?
          猜你喜欢
          • 2015-07-10
          • 1970-01-01
          • 1970-01-01
          • 2010-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多