C#不变性和平等

kof*_*fus -2 c#

我正在尝试创建和使用只有不可变类,其中所有字段都是只读不可变类型,尽管可能有其他字段是可变的并且不被认为是对象状态的一部分(主要是缓存的哈希码).

在实现IEquatable时,我会像对非不可变对象一样

也就是说,

public bool Equals(MyImmutableType o) => 
  object.Equals(this.x, o.x) && object.Equals(this.y, o.y);
Run Code Online (Sandbox Code Playgroud)

现在这是不可变的,这似乎是低效的,对象永远不会改变,如果我可以计算并存储一些独特的指纹,我可以简单地比较指纹而不是整个字段(可以称之为自己的Equals等).

我想知道什么是一个很好的解决方案呢?将BinaryFormatter+ MD5值得探索?

Eri*_*ert 7

由于您已经覆盖Equals,因此您还需要重载GetHashCode.请记住,基本规则GetHashCode平等对象具有相等的哈希值.

因此,你已经被覆盖了GetHashCode.

由于需要等对象具有相同的哈希码,因此可以将Equals实现为:

public static bool Equals(M a, M b)
{
  if (object.ReferenceEquals(a, b)) return true;
  // If both of them are null, we're done, but maybe one is.
  if (object.ReferenceEquals(null, a)) return false;
  if (object.ReferenceEquals(null, b)) return false;
  // Both are not null.
  if (a.GetHashCode() != b.GetHashCode()) return false;
  if (!object.Equals(a.x, b.x)) return false;
  if (!object.Equals(a.y, b.y)) return false;
  return true;
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以Equals通过调用静态帮助程序来实现任意数量的实例版本.也是超载==,!=而你在它.

该实施需要尽可能多的早期出局.当然,表现最差的情况是我们有价值平等而不是参考平等,但这也是最罕见的情况!在实践中,大多数对象彼此不相等,并且大多数彼此相等的对象是相等的参考.在99%的案例中,我们在四个或更少的高效比较中得到了正确的答案.

如果您处于这样一种情况,即对于价值相等但参考不相等的对象非常普遍,那么在工厂解决问题; 记住工厂!

  • @kofifus:罕见的情况是`a`和`b`值相等但参考不相等.在这里,选择宇宙中的任何两个对象; 他们是参考不平等和哈希不等的几率是好的,所以我们首先得到这个案例.现在假设他们是平等的.两个对象相等的可能性有多大,但*不是*引用相等?在绝大多数情况下,我拥有价值相等的对象,它们也是相同的参考*因为我不会绕过大量相同信息的冗余副本*. (2认同)
  • @Corey:你的理论是,在你打算纠正专家的尝试时,以错误的方式思考它是"更准确"的; 你*可能*想重新审视这个理论.**将其视为"平等对象必须具有相同的哈希码"更为准确.**正如您刚刚演示的那样,即使是聪明的人也很难在一个句子中正确推理出多个对立面*.如果可能的话,可以推理*相等*,而不是*不相等*; 你会更有可能做对! (2认同)