C#中的泛型值相等(标识)

时间:2013-06-24 22:33:55

标签: c# generics

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

目前我这样做:

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

3 个答案:

答案 0 :(得分:5)

您应该只能将object.Equals用于值类型:

 return typeof(T).IsValueType
    ? object.Equals(x, y)
    : ReferenceEquals(x, y);

答案 1 :(得分:0)

不幸的是,.NET只定义了一个标准的虚拟Equals方法和一个GetHashCode方法,即使有两个逻辑问题,例如一个问题可能会问(如果假设{{,则问题最简单) 1}}和X是相同类型的变量):

  1. 可以用“Y”代替“X”,反之亦然,而不影响其任何成员现在或将来的行为吗?
  2. 如果要同时对“X”的目标的所有引用指向“Y”,并且对“Y”的目标的所有引用都指向“X”,那么`X的所有成员`和'Y`继续表现相同?

假设YX包含对两个类型Y的对象的引用,这两个对象目前包含值42.一些外部代码保存对int[1]的同一实例的引用,并即将增加它。如果要将Y更改为指向与X相同的实例,则会更改Y的未来值。

另一方面,假设两个对象每个都有一个私有字段,每个对象都拥有宇宙中任何位置存在的唯一引用到它自己的X[0],它们都保持并且将始终保持值42,并且都没有导致在该实例上调用int[1]。尽管RuntimeHelpers.GetHashCode()是一个可变类型,但上述两个实例应该被认为是等价的,因为交换&#34;所有引用&#34; [即第一个引用第二个的唯一引用]对程序行为没有影响。但是,如果一个数组保持23而另一个数组保持23,则交换引用将交换哪个对象持有对23的引用,哪个具有27。

请注意,如果添加语句&#34;不同类型的对象不能等效,因为他们的int[1]方法必然会有不同的行为&#34;,那么上面的两个问题都可以有意义且毫不含糊地回答对象任何类类型,第二个可以有意义地回答任何值类型。答案将构成对等和价值平等的有意义的定义。 .NET GetType()覆盖的正常行为倾向于使引用类型回答第一个问题(代码更可能对它感兴趣)并且值类型回答第二个问题(因为第一个问题对它们没有意义)。既然听起来像是你想要的默认行为,也许你可以描述某些情况是不是这样?

[注意:像Equals这样的一些.NET类型以loosy-goosy方式定义Decimal;通过通用虚拟方法回答上面的两个问题是很好的。]

答案 2 :(得分:0)

对您感兴趣的类型实施 IEquatable&lt; T&gt; ,以及 object.Equals() object.GetHashCode(),或者为您的类型使用者提供 IEqualityComparer&lt; T&gt; 的实例。

DOT NET 没有实现你的平等定义,因为它不会是我的,或者弗雷德在街上。相反,它提供了一些工具,让您可以准确地构建您需要的工具,而无需踩到我的脚趾或者我需要构建的东西......