5

比较相同泛型类型的两个实例的最佳(最简洁和最佳)方法是什么,以便比较引用类型的身份(相同的对象,所以不调用Equals)和类型的值相等

目前我这样做:

static bool IdentityEquals<T>(T x, T y)
{
    return typeof(T).IsValueType
        ? EqualityComparer<T>.Default.Equals(x, y)
        : ReferenceEquals(x, y);
}
4

3 回答 3

5

您应该能够仅object.Equals用于值类型:

 return typeof(T).IsValueType
    ? object.Equals(x, y)
    : ReferenceEquals(x, y);
于 2013-06-24T22:39:57.047 回答
0

在您感兴趣的类型上实现IEquatable<T>以及 object.Equals( )object.GetHashCode()的覆盖,或者为您的类型使用者提供IEqualityComparer<T>的实例。

DOT NET没有实现你对平等的定义,因为那样它就不是我的,也不是 Fred 的。相反,它为您提供了工具来准确地构建您需要的东西,而无需踩到我的脚趾或咬住我需要构建的东西。

于 2013-06-24T23:47:27.620 回答
0

不幸的是,.NET 只定义了一种标准虚拟Equals方法和一种GetHashCode方法,即使这样的问题可能会提出两个逻辑问题(如果假设X并且Y是相同类型的变量,那么问题是最简单的):

  1. 是否可以用引用“Y”来替换“X”,反之亦然,而不影响其中任何成员当前或未来的行为?
  2. 如果要同时使对“X”目标的所有引用都指向“Y”,并且对“Y”目标的所有引用都指向“X”,那么“X”和“Y”的所有成员会继续吗?表现一样吗?

假设XY持有对int[1]当前包含值 42 的两个类型对象的引用。一些外部代码持有对与 相同的实例的引用Y,并且即将增加它。如果要更改X为指向与 相同的实例Y,那将更改 的未来值X[0]

另一方面,假设两个对象每个都有一个私有字段,每个对象都拥有一个存在于宇宙中任何地方的对自己的引用,int[1]并且都持有并将始终持有值 42,并且两者都没有导致RuntimeHelpers.GetHashCode()被调用那个例子。即使int[1]是可变类型,上述两个实例也应该被认为是等效的,因为将第一个的“所有引用”[即唯一的引用]与对第二个的所有引用交换对程序行为没有影响。然而,如果一个数组持有 23 而另一个持有 27,则交换引用将交换哪个对象持有对 23 的引用,而哪个对象持有 27。

请注意,如果添加“不同类型的对象不能等价,因为它们的GetType()方法必然会表现不同”的陈述,那么对于任何类类型的对象,上述两个问题都可以得到有意义且明确的回答,而第二个问题对于任何类类型的对象都可以得到有意义的回答。任何值类型。答案将构成对等价和价值平等的有意义的定义。.NET 覆盖的正常行为Equals倾向于让引用类型回答第一个问题(代码更可能对它感兴趣),让值类型回答第二个问题(因为第一个问题对他们来说毫无意义)。由于听起来默认行为是您想要的,也许您可​​以描述是否存在某些情况不是这样?

[注意:一些 .NET 类型,例如以 loosy-goosy 方式Decimal定义Equals;上面的两个问题最好用通用的虚拟方法来回答]。

于 2013-06-24T23:40:58.647 回答