Я подумал, что пришло время обновить реализацию предыдущих ответов до .Net4.0 +, где дженерики больше не нужны благодаря контравариантности интерфейса IEqualityComparer<in T>
:
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
public sealed class ReferenceEqualityComparer
: IEqualityComparer, IEqualityComparer<object>
{
private ReferenceEqualityComparer() { }
public static readonly ReferenceEqualityComparer Default
= new ReferenceEqualityComparer();
public /*new*/ bool Equals(object x, object y)
{
return x == y; // This is reference equality! (See explanation below)
}
public int GetHashCode(object obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
Теперь должен существовать только один экземпляр для всей вашей проверки на равенство ссылок вместо одного для каждого типа T
, как было раньше.
Вам больше не нужно указывать T
каждый раз, когда вы хотите использовать это, а также избегать загрязнения ненужными универсальными типами среды выполнения.
Что касается того, почему x == y
является ссылочным равенством, это потому, что ==
operator является статическим методом, что означает, что он разрешается во время компиляции, а во время компиляции аргументы x
и y
имеют тип object
.
Фактически это то, что Object.ReferenceEquals(object, object)
метод source code нравиться:
public static bool ReferenceEquals(object objA, object objB) {
return objA == objB;
}
Чтобы прояснить для тех, кто не знаком с концепциями Ковариация и Контравариантность ...
class MyClass
{
ISet<MyClass> setOfMyClass = new HashSet<MyClass>(ReferenceEqualityComparer.Default);
}
... приведенный выше код компилируется; Обратите внимание, что здесь не указано HashSet<object>
.
person
AnorZaken
schedule
20.02.2016