Я хотел бы использовать Distinct()
с моими данными, объявленными как IEnumerable<KeyValuePair<IdentType, string>>
. В этом случае я должен реализовать свой собственный IEqualityComparer
и есть мой вопрос:
Есть ли разница между нижеприведенными реализациями?
public int GetHashCode(KeyValuePair<IdentType, string> obj) {
return EqualityComparer<string>.Default.GetHashCode(obj.Value);
}
а также
public int GetHashCode(KeyValuePair<IdentType, string> obj) {
return obj.Value.GetHashCode();
}
Между вашими двумя методами существует только небольшая разница.
EqualityComparer<string>.Default
вернет класс типа GenericEqualityComparer<T>
если класс implments IEquateable<T>
(какая строка). Так что GetHashCode(obj.Value)
получает вызов
public override int GetHashCode(T obj) {
if (obj == null) return 0;
return obj.GetHashCode();
}
который является тем же самым, что вы вызываете obj.Value.GetHashCode();
напрямую, за исключением того факта, что если у вас есть нулевая строка, то по умолчанию сопоставитель вернет 0, а версия прямого вызова будет выбрана исключение с нулевой ссылкой.
Одно из отличий заключается в том, что EqualityComparer<string>.Default.GetHashCode
не будет разбиваться, когда вы передадите ему null
.
using System;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
var n = EqualityComparer<string>.Default.GetHashCode(null);
Console.WriteLine(n);
}
}
Кроме того, результаты будут идентичными по дизайну, потому что System.String
реализует IEquatable<System.String>
Свойство Default проверяет, реализует ли тип T общий интерфейс
System.IEquatable<T>
и, если это так, возвращаетEqualityComparer<T>
который вызывает реализацию методаIEquatable<T>.Equals
. В противном случае он возвращаетEqualityComparer<T>
, как это предусмотреноT
Нет. Это не так. Реализация будет такой же, поскольку оба они называют GetHashCode()
для фактического класса, в этом случае string
.
В конце концов, метод CreateComparer
внутри EqualityComparer
создает GenericEqualityComparer
, а реализация его GetHashCode
:
public override int GetHashCode(T obj) {
if (obj == null) return 0;
return obj.GetHashCode();
}
В этом случае obj
будет исходной string
которой в противном случае вы могли бы вызвать GetHasCode
. Единственный случай, который заставит его вести себя по-другому, - это когда ваша string
равна null
.
Только один: сопоставитель равенства GetHashCode
вернет 0, если строка равна нулю, тогда как вторая реализация вызовет исключение.