Implementing Equals() for reference types is harder than it seems. My current canonical implementation goes like this:
为引用类型实现Equals()比看起来更难。我目前的规范实现如下:
public bool Equals( MyClass obj )
{
// If both refer to the same reference they are equal.
if( ReferenceEquals( obj, this ) )
return true;
// If the other object is null they are not equal because in C# this cannot be null.
if( ReferenceEquals( obj, null ) )
return false;
// Compare data to evaluate equality
return _data.Equals( obj._data );
}
public override bool Equals( object obj )
{
// If both refer to the same reference they are equal.
if( ReferenceEquals( obj, this ) )
return true;
// If the other object is null or is of a different types the objects are not equal.
if( ReferenceEquals( obj, null ) || obj.GetType() != GetType() )
return false;
// Use type-safe equality comparison
return Equals( (MyClass)obj );
}
public override int GetHashCode()
{
// Use data's hash code as our hashcode
return _data.GetHashCode();
}
I think that this covers all corner (inheritance and such) cases but I may be wrong. What do you guys think?
我认为这涵盖了所有角落(继承等),但我可能错了。你们有什么感想?
5 个解决方案
#1
4
I wrote a fairly comprehensive guide to this a while back. For a start your equals implementations should be shared (i.e. the overload taking an object should pass through to the one taking a strongly typed object). Additionally you need to consider things such as your object should be immutable because of the need to override GetHashCode. More info here:
我前一段时间写了一篇相当全面的指南。首先,应该共享equals实现(即,将对象的重载传递给采用强类型对象的实现)。此外,您需要考虑诸如您的对象应该是不可变的事情,因为需要重写GetHashCode。更多信息:
http://gregbeech.com/blog/implementing-object-equality-in-dotnet
#2
1
Better hope that this._data is not null if it's also a reference type.
如果它也是引用类型,那么希望this._data不为null。
public bool Equals( MyClass obj )
{
if (obj == null) {
return false;
}
else {
return (this._data != null && this._data.Equals( obj._data ))
|| obj._data == null;
}
}
public override bool Equals( object obj )
{
if (obj == null || !(obj is MyClass)) {
return false;
}
else {
return this.Equals( (MyClass)obj );
}
}
public override int GetHashCode() {
return this._data == null ? 0 : this._data.GetHashCode();
}
#3
0
Concerning inheritance, I think you should just let the OO paradigm does its magic.
关于继承,我认为你应该让OO范例发挥其魔力。
Specifically, the GetType()
check should be removed, it might break polymorphism down the line.
具体来说,应该删除GetType()检查,它可能会破坏多行性。
#4
0
I agree with chakrit, objects of different types should be allowed to be semantically equal if they have the same data or ID.
我同意chakrit,如果具有相同的数据或ID,则应允许不同类型的对象在语义上相等。
Personally, I use the following:
就个人而言,我使用以下内容:
public override bool Equals(object obj)
{
var other = obj as MyClass;
if (other == null) return false;
return this.data.Equals(other.data);
}
#5
0
It depends on whether you're writing a value type or a reference type. For a sortable value type, I recommend this: A code snippet for Visual Studio 2005 that implements a skeleton value type adhering to Framework Design Guidelines
这取决于您是在编写值类型还是引用类型。对于可排序的值类型,我建议这样:Visual Studio 2005的代码片段,它实现遵循框架设计指南的框架值类型
#1
4
I wrote a fairly comprehensive guide to this a while back. For a start your equals implementations should be shared (i.e. the overload taking an object should pass through to the one taking a strongly typed object). Additionally you need to consider things such as your object should be immutable because of the need to override GetHashCode. More info here:
我前一段时间写了一篇相当全面的指南。首先,应该共享equals实现(即,将对象的重载传递给采用强类型对象的实现)。此外,您需要考虑诸如您的对象应该是不可变的事情,因为需要重写GetHashCode。更多信息:
http://gregbeech.com/blog/implementing-object-equality-in-dotnet
#2
1
Better hope that this._data is not null if it's also a reference type.
如果它也是引用类型,那么希望this._data不为null。
public bool Equals( MyClass obj )
{
if (obj == null) {
return false;
}
else {
return (this._data != null && this._data.Equals( obj._data ))
|| obj._data == null;
}
}
public override bool Equals( object obj )
{
if (obj == null || !(obj is MyClass)) {
return false;
}
else {
return this.Equals( (MyClass)obj );
}
}
public override int GetHashCode() {
return this._data == null ? 0 : this._data.GetHashCode();
}
#3
0
Concerning inheritance, I think you should just let the OO paradigm does its magic.
关于继承,我认为你应该让OO范例发挥其魔力。
Specifically, the GetType()
check should be removed, it might break polymorphism down the line.
具体来说,应该删除GetType()检查,它可能会破坏多行性。
#4
0
I agree with chakrit, objects of different types should be allowed to be semantically equal if they have the same data or ID.
我同意chakrit,如果具有相同的数据或ID,则应允许不同类型的对象在语义上相等。
Personally, I use the following:
就个人而言,我使用以下内容:
public override bool Equals(object obj)
{
var other = obj as MyClass;
if (other == null) return false;
return this.data.Equals(other.data);
}
#5
0
It depends on whether you're writing a value type or a reference type. For a sortable value type, I recommend this: A code snippet for Visual Studio 2005 that implements a skeleton value type adhering to Framework Design Guidelines
这取决于您是在编写值类型还是引用类型。对于可排序的值类型,我建议这样:Visual Studio 2005的代码片段,它实现遵循框架设计指南的框架值类型