我正在开发一个C#项目,直到现在,我已经使用了不可变对象和工厂来确保始终可以比较Foo
类型的对象与==
的相等性。
Foo
个对象无法更改,并且工厂始终为给定的参数集返回相同的对象。这很好用,在整个代码库中我们假设==
总是用于检查相等性。
现在我需要添加一些引入边缘情况的功能,但这并不总是有效。最简单的方法是为该类型重载operator ==
,以便项目中的其他代码都不需要更改。但这让我觉得有点代码味道:重载operator ==
而不是Equals
看起来很奇怪,我已经习惯了==
检查引用相等的约定,Equals
检查对象是否相等(或任何术语)。
这是一个合理的问题,还是我应该继续过载operator ==
?
答案 0 :(得分:85)
重载 ==
与覆盖等于
当你有表达式
时if (x == y) {
用于比较变量x和y的方法在编译时确定。这是运算符重载。声明x和y时使用的类型用于定义用于比较它们的方法。 x和y中的实际类型(即子类或接口实现)是无关紧要的。请考虑以下事项。
object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference
if (x == y) { // evaluates to FALSE
以及
string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference
if (x == y) { // evaluates to TRUE
这表明用于声明变量x和y的类型用于确定用于评估==的方法。
通过比较,根据变量x中的实际类型,在运行时确定等于。 Equals是Object上的一个虚方法,其他类型可以并且确实覆盖它。因此,以下两个例子都评估为真。
object x = "hello";
object y = 'h' + "ello"; // ensure it's a different reference
if (x.Equals(y)) { // evaluates to TRUE
以及
string x = "hello";
string y = 'h' + "ello"; // ensure it's a different reference
if (x.Equals(y)) { // also evaluates to TRUE
答案 1 :(得分:27)
我认为标准是对于大多数类型,.Equals检查对象的相似性,而运算符==
检查引用相等。
我认为最佳做法是,对于不可变类型,运算符==
应该检查相似性,以及.Equals
。如果您想知道它们是否真的是同一个对象,请使用.ReferenceEquals
。有关此示例,请参阅C#String
类。
答案 2 :(得分:7)
对于不可变类型,我认为重载==
以支持值相等没有任何问题。我不认为我会覆盖==
而不会覆盖Equals
以获得相同的语义。如果您覆盖==
并且由于某种原因需要检查引用相等性,则可以使用Object.ReferenceEquals(a,b)
。
答案 3 :(得分:7)
它绝对闻起来。当重载==
时,您应该确保Equals()
和GetHashCode()
都一致。请参阅MSDN guidelines。
这个似乎没问题的唯一原因是你将你的类型描述为不可变的。
答案 4 :(得分:6)
示例显示如何根据MSFT guidelines(下文)实现此目的。注意,当覆盖Equals时,您还需要覆盖GetHashCode()。希望这有助于人们。
public class Person
{
public Guid Id { get; private set; }
public Person(Guid id)
{
Id = id;
}
public Person()
{
Id = System.Guid.NewGuid();
}
public static bool operator ==(Person p1, Person p2)
{
bool rc;
if (System.Object.ReferenceEquals(p1, p2))
{
rc = true;
}
else if (((object)p1 == null) || ((object)p2 == null))
{
rc = false;
}
else
{
rc = (p1.Id.CompareTo(p2.Id) == 0);
}
return rc;
}
public static bool operator !=(Person p1, Person p2)
{
return !(p1 == p2);
}
public override bool Equals(object obj)
{
bool rc = false;
if (obj is Person)
{
Person p2 = obj as Person;
rc = (this == p2);
}
return rc;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
答案 5 :(得分:5)
根据Microsofts自己的最佳实践,Equals方法和equals(==)重载的结果应该是相同的。