C#运算符==:什么是标准实践(参考/值相等)?
说明:C#运算符==:什么是标准实践(参考/值相等)?,c#,C#,说明: Equals()比较两个对象的值 ReferenceEquals()比较它们的引用 对于引用类型,operator==默认情况下比较引用,而对于值类型,它使用反射执行(AFAIK)相等于Equals()的操作 所以。在这种情况下,我需要根据两种引用类型的值来比较它们。我可以显式调用Equals()或重载操作符==,以执行所需的比较 然而,重载操作符==进行值比较有点违反了最小惊讶原则。另一方面,显式调用两个对象Equals看起来太过分了 这里的标准做法是什么 我知道如何重写Equa
比较两个对象的值Equals()
比较它们的引用ReferenceEquals()
operator==
默认情况下比较引用,而对于值类型,它使用反射执行(AFAIK)相等于Equals()的操作
所以。在这种情况下,我需要根据两种引用类型的值来比较它们。我可以显式调用Equals()
或重载操作符==
,以执行所需的比较
然而,重载操作符==
进行值比较有点违反了最小惊讶原则。另一方面,显式调用两个对象Equals
看起来太过分了
这里的标准做法是什么
我知道如何重写
Equals()
。问题是,覆盖运算符==
来测试引用类型上的值是否等于是否是普遍接受的做法,还是普遍接受的做法是显式调用Equals/ReferenceEquals来显式指定所需的比较
什么是标准实践
“标准实践”是,如果要检查两个元素是否相等,而这两个元素不是引用相等,则需要实现IEquatable
,它引入了Equals(t other)
方法,并重写GetHashCode
。这样,您就可以控制比较这两个对象的方式。通常,这包括覆盖==
和=代码>操作符
而对于值类型,它使用
反思
仅当值类型具有引用类型的成员时。如果都是值类型,则:
问题是,是否可以普遍接受否决
运算符==测试引用类型上的值相等性
这真的取决于你在做什么。建议您在重写Equals
后重写==
运算符,因为您需要一致的行为值相等语义。这取决于您对两个对象之间相等的定义
尽管如此,如果一个对象是可变的,那么进行值比较可能会导致两个对象被视为相等的奇怪场景,但之后,一个对象发生了变化。这肯定应该根据具体情况进行分析。通常,覆盖等于就足够了
问题是,是否可以普遍接受否决
运算符==用于测试值是否相等
它取决于对象,如果对象是不可变的,则可以重写=
运算符,否则不能重写。(记住,它们只是指导方针)
见:
默认情况下,运算符==通过
确定两个引用是否指示同一对象。
因此,引用类型不必在中实现运算符==
以获得此功能当一个类型是不可变的时
是,实例中包含的数据不能更改,
重载运算符==比较值相等而不是引用相等可能很有用,因为作为不可变对象,它们
只要它们具有相同的值,就可以认为是相同的它
在非不变类型中重写运算符==不是一个好主意。
Equals()
执行两个对象的值比较
事实并非如此。值类型上的object.Equals
的默认行为是使用它们的相等定义来比较每个字段,引用类型的默认行为是比较它们的引用。可以重写它来执行您希望它执行的任何操作。在这方面,它与=
操作符完全相同
=
运算符和Equals
之间的唯一区别在于Equals
将对第一个(但不是第二个)操作数执行虚拟分派,根据该对象的运行时类型查找方法的实现。==
操作符是完全静态绑定的;它只考虑两个操作数的编译时类型。除了绑定方面的差异之外,两者都具有相同的默认行为,并且都可以被覆盖以提供您想要的任何实现
标准做法是始终确保Equals
和operator==
的行为与您的类型相同。如果重写Equals
方法以更改相等语义,则还应重载=
运算符以提供*相同语义',反之亦然 给代码赋予语义是一种很好的做法。所以,如果引用比较确实是您应该关心的事情,那么在您的类中使用默认行为;否则,应该使用应用程序上下文相关逻辑进行比较。(所有平等成员的行为都是一致的,如Equals
,GetHashCode
和运算符)请参阅:不是重复的,因为我问的是普遍接受的标准,而不是最快/任何方法。不同的问题。对于引用类型,除非您重写Equals
,否则它也会执行引用相等。通常,首先检查两种类型的引用相等,如果它们不匹配,然后检查值相等(如果需要)。
这只是一种优化,对于实际的语义来说并不重要。如果要删除该检查以实际更改该方法的结果,则需要出现严重错误。这意味着当对象与自身进行比较时,值检查需要失败。请注意,如果基于实际值的检查非常快(如果只有一个成员要比较,并且可以快速检查),那么
// 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);