C#operator ==:什么是标准实践(参考/值相等)?

时间:2015-07-06 13:39:47

标签: c#

说明:

  • Equals()比较两个对象的值。
  • ReferenceEquals()比较他们的参考资料。

对于引用类型operator==默认情况下比较引用,而对于值类型,它使用反射执行(AFAIK)等效的Equals()。

因此。我有一种情况,我需要通过它们的值比较两个引用类型。我可以明确地调用Equals()或者我可以重载operator==来执行所需的比较。

然而,重载operator==进行价值比较有点违反了最不惊讶的原则。另一方面,显式调用双对象Equals看起来有点矫枉过正。

这里的标准做法是什么?

我知道如何覆盖Equals()。问题是,覆盖operator==以测试引用类型上的相等是否通常是可以接受的,或者是否通常接受的做法是显式调用Equals / ReferenceEquals明确指定你想要的比较。

4 个答案:

答案 0 :(得分:3)

  

什么是标准做法?

&#34;标准做法&#34;是,如果要检查两个元素是否相等而不是引用相等,则需要实现IEquatable<T>,它引入Equals(T other)方法,并覆盖GetHashCode。这样,就可以控制这两个对象的比较方式。通常,这包括覆盖==!=运算符。

  

而对于值类型,它使用相当于Equals()的(AFAIK)执行   反射。

仅当您的值类型具有作为引用类型的成员时。如果是所有值类型,it will do a bit comparison of these two objects

// if there are no GC references in this object we can avoid reflection 
// and do a fast memcmp
if (CanCompareBits(this))
    return FastEqualsCheck(thisObj, obj);
  

问题是覆盖是否通常是可以接受的   operator ==测试引用类型的值相等性

这实际上取决于你正在做什么。一旦覆盖==,建议覆盖Equals运算符,因为您需要一致的行为值相等语义。这取决于您对两个对象之间的相等性的定义。

虽然,如果一个对象是可变的,那么进行值比较可能会导致奇怪的情况,其中两个对象被认为是相等的,但后来有一个是变异的。绝对应该根据每个案例进行分析。通常,覆盖Equals就足够了。

答案 1 :(得分:2)

  

P = pic.Problem() Rho = P.add_variable('Rho',(n,n),'hermitian') P.add_constraint(pic.trace(Rho)==1) P.add_constraint(Rho>>0) RhoQOBJ = Qobj(Rho) RhoABtr = ptrace(RhoQOBJ, [0,1]) RhoABqbj = partial_transpose(RhoABtr, [0], method='dense') RhoAB = RhoABqbj.full() 执行两个对象的值比较。

事实并非如此。 Equals()对值类型的默认行为是使用它们的相等定义来比较每个字段,引用类型的默认行为是比较它们的引用。可以覆盖它做任何你想做的事情。在这方面,它与object.Equals运算符完全相同。

==运算符和==之间的唯一区别是Equals将在第一个(但不是第二个)操作数上执行虚拟调度,找到基于该方法的实现在该对象的运行时类型上。 Equals运算符完全静态绑定;它只考虑两个操作数的编译时类型。除了这种绑定差异之外,它们都具有相同的默认行为,并且可以覆盖它们以提供您想要的任何实现。

标准做法是始终确保==Equals的行为与您的类型相同。如果重写operator ==方法来更改相等语义,那么您还应该重载Equals运算符以提供*相同的语义`,反之亦然。

答案 2 :(得分:1)

  

问题是覆盖是否通常是可以接受的   operator ==测试值相等

它取决于对象,如果对象是不可变的,那么你可以覆盖==运算符,否则不会。 (请记住它们只是指导方针)

请参阅:Guidelines for Overriding Equals() and Operator == (C# Programming Guide)

  

默认情况下,运算符==测试引用相等性   确定两个引用是否表示相同的对象。   因此,引用类型不必实现operator == in   为了获得这个功能。 当一个类型是不可变的时,那个   是,实例中包含的数据无法更改,   重载operator ==比较值相等而不是引用相等可能很有用因为,作为不可变对象,它们   只要具有相同的值,就可以认为是相同的。的它   在非不可变类型中覆盖operator ==不是一个好主意。

答案 3 :(得分:0)

为您的代码赋予语义含义是一种很好的做法。因此,如果您应该关注参考比较,请使用类的默认行为;否则应使用应用程序上下文相关逻辑进行比较。 (具有EqualsGetHashCode和运算符等所有平等成员的一致行为