IEquatable 和仅仅重写 Object.Equals() 之间有什么区别?
我希望我的 Food
类能够在它等于 Food
的另一个实例时进行测试。稍后我将针对 List 使用它,并且我想使用它的 List.Contains()
方法。我应该实现 IEquatable
还是只重写 Object.Equals()
?来自 MSDN:
此方法通过以下方式确定相等性 使用默认的相等比较器, 由对象的定义 的实施 T 的 IEquatable.Equals 方法 (列表中值的类型)。
所以我的下一个问题是:.NET 框架的哪些函数/类使用 Object.Equals()
?我应该首先使用它吗?
I want my Food
class to be able to test whenever it is equal to another instance of Food
. I will later use it against a List, and I want to use its List.Contains()
method. Should I implement IEquatable<Food>
or just override Object.Equals()
? From MSDN:
This method determines equality by
using the default equality comparer,
as defined by the object's
implementation of the
IEquatable.Equals method for T
(the type of values in the list).
So my next question is: which functions/classes of the .NET framework make use of Object.Equals()
? Should I use it in the first place?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
主要原因是性能。当 .NET 2.0 中引入泛型时,他们能够添加一堆简洁的类,例如
List
、Dictionary
、HashSet< ;T>
等。这些结构大量使用GetHashCode
和Equals
。但对于值类型,这需要装箱。IEquatable
让结构实现强类型Equals
方法,因此不需要装箱。因此,在将值类型与泛型集合一起使用时,性能会更好。引用类型没有那么多好处,但
IEquatable
实现确实可以让您避免来自System.Object
的强制转换,如果频繁调用,这可能会产生影响。如Jared Parson 的博客 不过,您必须仍然实现标准
Object.Equals
和Object.GetHashcode< /代码> 覆盖。
The main reason is performance. When generics were introduced in .NET 2.0 they were able to add a bunch of neat classes such as
List<T>
,Dictionary<K,V>
,HashSet<T>
, etc. These structures make heavy use ofGetHashCode
andEquals
. But for value types this required boxing.IEquatable<T>
lets a structure implement a strongly typedEquals
method, so no boxing is required. Thus much better performance when using value types with generic collections.Reference types don't benefit as much, but the
IEquatable<T>
implementation does let you avoid a cast fromSystem.Object
which can make a difference if it's called frequently.As noted on Jared Parson's blog though, you must still implement the standard
Object.Equals
andObject.GetHashcode
overrides.根据 MSDN:
因此,两者之间似乎没有真正的功能差异,只是可以根据类的使用方式来调用其中一个。从性能的角度来看,最好使用通用版本,因为没有与之相关的装箱/拆箱惩罚。
从逻辑的角度来看,实现接口也更好。重写该对象并不能真正告诉任何人您的类实际上是相等的。覆盖可能只是一个不执行任何操作的类或浅层实现。使用该接口明确表示:“嘿,这个东西对于相等性检查是有效的!”这只是更好的设计。
According to the MSDN:
So it seems that there's no real functional difference between the two except that either could be called depending on how the class is used. From a performance standpoint, it's better to use the generic version because there's no boxing/unboxing penalty associated with it.
From a logical standpoint, it's also better to implement the interface. Overriding the object doesn't really tell anyone that your class is actually equatable. The override may just be a do nothing class or a shallow implementation. Using the interface explicitly says, "Hey, this thing is valid for equality checking!" It's just better design.
用一个实际的例子来扩展乔希的说法。 +1 给乔什 - 我正要在我的答案中写同样的内容。
这样,我就拥有了可重用的 Equals() 方法,该方法可以开箱即用地用于我的所有派生类。
Extending what Josh said with a practical example. +1 to Josh - I was about to write the same in my answer.
This way, I have re-usable Equals() method that works out of the box for all my derived classes.
如果我们调用object.Equals,它会强制对值类型进行昂贵的装箱。这在性能敏感的场景中是不可取的。解决方案是使用
IEquatable
。IEquatable
背后的想法是,它提供与object.Equals
相同的结果,但速度更快。约束where T : IEquatable
必须与如下泛型类型一起使用。否则,它会绑定到
slower object.Equals()
。If we call
object.Equals
, it forces to expensive boxing on value types. This is undesirable in performance-sensitive scenarios. The solution is to useIEquatable<T>
.The idea behind
IEquatable<T>
is that it gives the same result asobject.Equals
but more quickly. The constrainwhere T : IEquatable<T>
must be used with generic types like below.otherwise, it binds to
slower object.Equals()
.