naw*_*fal 7 c# generics equality iequatable
我知道GetHashCode在实现自定义相等性检查时重写的重要性- 我已经实现了IEquality<T>接口,以及Equals 此处讨论的泛型和非泛型之间的区别.现在有一个重写的意义Equals(object t)吗?难道一切都不是通用的Equals(T t)吗?
public override int GetHashCode() //required for hashsets and dictionaries
{
return Id;
}
public bool Equals(T other) //IEquatable<T> here
{
return Id == other.Id;
}
public override bool Equals(object obj) //required??
{
return Equals(obj as T);
}
Run Code Online (Sandbox Code Playgroud)
sup*_*cat 10
未密封的类型不应该实现IEquatable<T>,因为确保(或甚至使其可能)派生类型将正确实现它的唯一方法是实现IEquatable<T>.Equals(T)以便调用Object.Equals(Object).由于整个目的IEquatable<T>是为了避免浪费CPU时间将事物转换为Object比较它们之前,调用的实现Object.Equals(Object)无法比未实现接口时将实现的默认行为更快地执行任何操作.
通过实施IEquatable<T>,密封类类型可以实现轻微的性能优势; 首选的样式是Object.Equals(Object)尝试将参数强制转换为T; 如果演员成功,请使用IEquatable<T>.Equals实现; 否则返回false.在任何情况下,IEquatable.Equals(T)与Object.Equals(Object)当传递同一个对象实例产生不同的结果.
结构类型可以使用与密封类类型相同的模式.尝试施法的方法略有不同,因为失败的施法不能返回null,但图案应该仍然相同.如果结构实现了一个变异接口(例如List<T>.Enumerator,一个实现的结构的情况IEnumerator<T>),相等比较的正确行为有点模糊.
请注意,顺便说一句,这IComparable<T>并IEquatable<T>应考虑相互独立.虽然通常情况是,当X.CompareTo(Y)为零时,X.Equals(Y)将返回true,但某些类型可能具有自然顺序,其中两个事物可能不同而没有对另一个进行排名.例如,一个人可能有一个NamedThing<T>组合a string和a 的类型T.这样的类型将支持名称的自然排序,但不一定支持T.两个实例,其名称匹配,但他们T的不同应该返回0了CompareTo,但false对Equals.因此,如果不更改,则覆盖IComparable不需要覆盖.GetHashCodeEquals
您当然应该覆盖Equals(object t)- 否则在使用该重载时可能会得到不正确的结果.你不能假设Equals(T other)是要调用的重载.
如果不覆盖它,将使用引用相等性,这意味着类似以下内容将返回false:
myObject1.Id = 1;
myObject2.Id = 1;
myObject1.Equals((object)myObject2); // false!
Run Code Online (Sandbox Code Playgroud)
另一个可能的问题是继承类 - 如果将类型与继承类型进行比较,则很容易失败.
来自msdn:
如果实现 IEquatable,还应该重写 Object.Equals(Object) 和 GetHashCode 的基类实现,以便它们的行为与 IEquatable.Equals 方法的行为一致。如果您确实重写了 Object.Equals(Object),则在调用类上的静态 Equals(System.Object, System.Object) 方法时也会调用您的重写实现。此外,您应该重载 op_Equality 和 op_Inequality 运算符。这确保了所有相等性测试返回一致的结果。
我也可以做更好的谷歌搜索。JaredPar 在 msdn 博客上有一篇关于该主题的好文章。
简而言之,最重要的是Equals(object obj):
对象类上的静态Equals(object obj1, object obj2)方法或ArrayList实例上的Contains(object item)等需要。
接受这一点,因为该链接在该主题上更全面。也感谢奥德..