如若IEquatable<吨>中IComparable的< T>对非密封类实现? [英] Should IEquatable<T>, IComparable<T> be implemented on non-sealed classes?

查看:98
本文介绍了如若IEquatable<吨>中IComparable的< T>对非密封类实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人有否 IEquatable&LT任何意见; T&GT; IComparable的&LT; T&GT; 一般应要求 T 密封(如果它是一个)<? / p>

因为我写了一组打算在一成不变的类的实现,以帮助基类的发生,我这个问题。的该基类的目的是提供功能性部分是自动实现(可应用于字段来控制相等比较使用类的字段具有属性一起)相等比较的。它应该是pretty不错,当我说完 - ​​我使用前pression树动态创建的每个 T ,所以编译比较函数比较函数应该很接近常规相等比较功能的性能。 (我使用上键入的System.Type 一个不变的词典和双重检查锁定存储的方式,这是合理的高性能生成的比较函数)

这虽然已经出现了一件事,就是功能用来检查会员领域的平等。我最初的意图是检查每个成员字段的类型(我称之为 X )实现 IEquatable&LT; X&GT; 。然而,经过一番思考,我不认为这是可以放心使用,除非 X 密封。原因是,如果 X 不是密封,我不能,如果肯定知道X 适当下放平等的检查,以一个虚拟的方法对 X ,从而允许亚型覆盖平等的比较。

这则带来了一个更普遍的问题 - 如果一个类型是不密封的,如果真的实现这些接口在所有?我想不会,因为我认为该接口的合同,不是两种类型可能会或可能不会是 X两个 X 类型之间进行比较(虽然他们当然必须 X 或亚型)。

你们觉得呢?如若 IEquatable&LT; T&GT; IComparable的&LT; T&GT; 避免对未密封类呢? (也让我不知道是否有一个这样的FxCop的规则)

我目前的想法是让我产生比较函数只使用 IEquatable&LT; T&GT; 对成员字段的 T 密封,而是用虚拟的Object.Equals(obj对象)如果 T 开封即使 T 工具 IEquatable&LT; T&GT; ,因为该领域可能存储亚型牛逼我怀疑大多数实现 IEquatable&LT; T&GT; 适当设计的继承


解决方案

我一直在思考这个问题了一下,有点考虑后,我同意实施 IEquatable&LT; T&GT; IComparable的&LT; T&GT; 只应在密封的类型进行。

我就来回一点,但转念一想下面的测试。在什么情况下应该下面再回到假的?恕我直言,2对象是相等或他们不是。

 公共无效EqualitySanityCheck&LT; T&GT;(T左,T右)其中T:IEquatable&LT; T&GT; {
  VAR equals1 = left.Equals(右);
  VAR equals2 =((IEqutable&LT; T&GT;)左).Equals(右);
  Assert.AreEqual(equals1,equals2);
}

IEquatable 1所述的结果; T&GT; 一个给定的对象应该具有相同的行为的Object.Equals 就任比较器是同等类型的。实施 IEquatable&LT; T&gt;在对象层次两次允许,并暗示,也有你的系统的前pressing平等的两种不同的方式。这很容易图谋任意数量的方案,其中 IEquatable&LT; T&GT; 的Object.Equals 将有所不同,因为有多个 IEquatable&LT; T&GT; 实现,但只有一个的Object.Equals 。因此,上面会失败,并在code创建一个有点混乱。

有些人可能会认为,实施 IEquatable&LT; T&GT; 在对象层次更高的观点是正确的,因为你要比较的对象属性的子集。在这种情况下,你应该赞成的IEqualityComparer&LT; T&GT; 这是专门设计来比较这些属性。

Anyone have any opinions on whether or not IEquatable<T> or IComparable<T> should generally require that T is sealed (if it's a class)?

This question occurred to me since I'm writing a set of base classes intended to aid in the implementation of immutable classes. Part of the functionality which the base class is intended to provide is automatic implementation of equality comparisons (using the class's fields together with attributes which can be applied to fields to control equality comparisons). It should be pretty nice when I'm finished - I'm using expression trees to dynamically create a compiled comparison function for each T, so the comparison function should be very close to the performance of a regular equality comparison function. (I'm using an immutable dictionary keyed on System.Type and double check locking to store the generated comparison functions in a manner that's reasonably performant)

One thing that has cropped up though, is what functions to use to check equality of the member fields. My initial intention was to check if each member field's type (which I'll call X) implements IEquatable<X>. However, after some thought, I don't think this is safe to use unless X is sealed. The reason being that if X is not sealed, I can't know for sure if X is appropriately delegating equality checks to a virtual method on X, thereby allowing a subtype to override the equality comparison.

This then brings up a more general question - if a type is not sealed, should it really implement these interfaces AT ALL?? I would think not, since I would argue that the interfaces contract is to compare between two X types, not two types which may or may not be X (though they must of course be X or a subtype).

What do you guys think? Should IEquatable<T> and IComparable<T> be avoided for unsealed classes? (Also makes me wonder if there is an fxcop rule for this)

My current thought is to have my generated comparison function only use IEquatable<T> on member fields whose T is sealed, and instead to use the virtual Object.Equals(Object obj) if T is unsealed even if T implements IEquatable<T>, since the field could potentially store subtypes of T and I doubt most implementations of IEquatable<T> are designed appropriately for inheritance.

解决方案

I've been thinking about this question for a bit and after a bit of consideration I agree that implementing IEquatable<T> and IComparable<T> should only be done on sealed types.

I went back and forth for a bit but then I thought of the following test. Under what circumstances should the following ever return false? IMHO, 2 objects are either equal or they are not.

public void EqualitySanityCheck<T>(T left, T right) where T : IEquatable<T> {
  var equals1 = left.Equals(right);
  var equals2 = ((IEqutable<T>)left).Equals(right);
  Assert.AreEqual(equals1,equals2);
}

The result of IEquatable<T> on a given object should have the same behavior as Object.Equals assuming the comparer is of the equivalent type. Implementing IEquatable<T> twice in an object hierarchy allows for, and implies, there are 2 different ways of expressing equality in your system. It's easy to contrive any number of scenarios where IEquatable<T> and Object.Equals would differ since there are multiple IEquatable<T> implementations but only a single Object.Equals. Hence the above would fail and create a bit of confusion in your code.

Some people may argue that implementing IEquatable<T> at a higher point in the object hierarchy is valid because you want to compare a subset of the objects properties. In that case you should favor an IEqualityComparer<T> which is specifically designed to compare those properties.

这篇关于如若IEquatable&LT;吨&gt;中IComparable的&LT; T&GT;对非密封类实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆