Сообщение Re: Правильный GetHashCode для сравнения byte[] по значению от 25.12.2016 9:45
Изменено 25.12.2016 9:57 hardcase
Здравствуйте, Shmj, Вы писали:
S>Т.к. GetHashCode возвращает int, то вовлечь достаточно 4 байта. Так же можно вовлечь длину массива (или 1 байт длины). Это будет и быстро и выполнять свои функции, то есть в большенстве случаев сработает. Согласны?
У меня есть утиллитка для сборки хэшей, использование очевидно:
Под профайлером эта радость гонялась, проблем пока не видел.
S>Т.к. GetHashCode возвращает int, то вовлечь достаточно 4 байта. Так же можно вовлечь длину массива (или 1 байт длины). Это будет и быстро и выполнять свои функции, то есть в большенстве случаев сработает. Согласны?
У меня есть утиллитка для сборки хэшей, использование очевидно:
public struct HashCode : IEquatable<HashCode>
{
public readonly int Value;
public HashCode(int value)
{
Value = value;
}
public HashCode(string text, StringComparer comparer)
{
Value = (object)text != null ? comparer.GetHashCode(text) : 0;
}
public override string ToString() =>
"HashCode: " + Value;
public override int GetHashCode() =>
Value;
public override bool Equals(object other) =>
other is HashCode && Equals((HashCode)other);
public bool Equals(HashCode other) =>
Value == other.Value;
public static bool operator ==(HashCode a, HashCode b) =>
a.Value == b.Value;
public static bool operator !=(HashCode a, HashCode b) =>
a.Value != b.Value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator int(HashCode hashCode) =>
hashCode.Value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add(int newValue) =>
new HashCode(unchecked((Value << 5) + Value ^ newValue));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add(bool flag) =>
Add(flag ? 1 : -1);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add<T>(T? obj)
where T : struct =>
obj.HasValue ? Add(obj.GetValueOrDefault().GetHashCode()) : this;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add<T>(T obj)
where T : class =>
obj != null ? Add(obj.GetHashCode()) : this;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add(string text, StringComparer comparer) =>
(object)text != null ? Add(comparer.GetHashCode(text)) : this;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode AddGeneric<T>(T obj) =>
Add(EqualityComparer<T>.Default.GetHashCode(obj));
public HashCode AddArray<T>(T[] arr)
{
if (arr == null) { return this; }
var count = arr.Length;
var hashCode = Add(count);
if (count > 0) { hashCode = hashCode.AddGeneric(arr[0]); }
if (count > 1) { hashCode = hashCode.AddGeneric(arr[count - 1]); }
return hashCode;
}
...
Под профайлером эта радость гонялась, проблем пока не видел.
Здравствуйте, Shmj, Вы писали:
S>На SOF рекомендуют перебирать все элементы массива:
На SOF рекомендуют много всякой ерунды
На практике же перебор массива — слишком затратная операция чтобы при каждом обращении к GetHashCode ее выполнять. Хэши сложных объектов необходимо кэшировать, и использовать в реализации Equals.
S>Т.к. GetHashCode возвращает int, то вовлечь достаточно 4 байта. Так же можно вовлечь длину массива (или 1 байт длины). Это будет и быстро и выполнять свои функции, то есть в большенстве случаев сработает. Согласны?
У меня есть утиллитка для сборки хэшей, использование очевидно:
Под профайлером эта радость гонялась, проблем пока не видел.
S>На SOF рекомендуют перебирать все элементы массива:
На SOF рекомендуют много всякой ерунды
На практике же перебор массива — слишком затратная операция чтобы при каждом обращении к GetHashCode ее выполнять. Хэши сложных объектов необходимо кэшировать, и использовать в реализации Equals.
S>Т.к. GetHashCode возвращает int, то вовлечь достаточно 4 байта. Так же можно вовлечь длину массива (или 1 байт длины). Это будет и быстро и выполнять свои функции, то есть в большенстве случаев сработает. Согласны?
У меня есть утиллитка для сборки хэшей, использование очевидно:
public struct HashCode : IEquatable<HashCode>
{
public readonly int Value;
public HashCode(int value)
{
Value = value;
}
public HashCode(string text, StringComparer comparer)
{
Value = (object)text != null ? comparer.GetHashCode(text) : 0;
}
public override string ToString() =>
"HashCode: " + Value;
public override int GetHashCode() =>
Value;
public override bool Equals(object other) =>
other is HashCode && Equals((HashCode)other);
public bool Equals(HashCode other) =>
Value == other.Value;
public static bool operator ==(HashCode a, HashCode b) =>
a.Value == b.Value;
public static bool operator !=(HashCode a, HashCode b) =>
a.Value != b.Value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator int(HashCode hashCode) =>
hashCode.Value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add(int newValue) =>
new HashCode(unchecked((Value << 5) + Value ^ newValue));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add(bool flag) =>
Add(flag ? 1 : -1);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add<T>(T? obj)
where T : struct =>
obj.HasValue ? Add(obj.GetValueOrDefault().GetHashCode()) : this;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add<T>(T obj)
where T : class =>
obj != null ? Add(obj.GetHashCode()) : this;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode Add(string text, StringComparer comparer) =>
(object)text != null ? Add(comparer.GetHashCode(text)) : this;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public HashCode AddGeneric<T>(T obj) =>
Add(EqualityComparer<T>.Default.GetHashCode(obj));
public HashCode AddArray<T>(T[] arr)
{
if (arr == null) { return this; }
var count = arr.Length;
var hashCode = Add(count);
if (count > 0) { hashCode = hashCode.AddGeneric(arr[0]); }
if (count > 1) { hashCode = hashCode.AddGeneric(arr[count - 1]); }
return hashCode;
}
...
Под профайлером эта радость гонялась, проблем пока не видел.