2016-05-09 2 views
10

Короткий вопросхеширования массив в C#

Как реализовать GetHashCode для Array.

Подробности

У меня есть объект, который переопределяет Equals, проверяя, что:

this.array[n] == otherObject.array[n] 

для всех n в array.

Естественно, я должен реализовать дополнительные GetHashCode. мне было интересно, если есть .NET способ сделать это, или если я должен реализовать свое собственное, что-то вроде

hash = hash^array[n] 

Разъяснения

Моего объекта содержит массив, и я заинтересован в GetHashCode для элементов массива. Например, мой код для эквивалентности массива - например, мой вопрос говорит, но, может быть, я был неясно, меня интересует GetHashCode (не Equals). Я говорю, что я, естественно, должен реализовать дополнительный GetHashCode, потому что это требование .NET для реализации этого после того, как Equals переопределено (для корректной работы Dictionary и т. Д.). Благодарю.

+0

Посмотрите на ответ, размещенный [здесь] (http://stackoverflow.com/a/7244729/833070). Другими словами, вам лучше реализовать свои собственные варианты или использовать другой инструмент, вы не можете использовать 'GetHashCode()' или 'Equals()' для массива – Draken

+0

Почему бы не сделать this.array [n]. Equals (otherObject.array [n]) 'для' n'? –

+1

Если вы хотите сравнить два массива для равенства, вы можете использовать расширение 'SequenceEqual' –

ответ

4

Для вычисления хэш-кода с использованием элементов массива, вы можете привести массив к IStructuralEquatable, а затем вызвать метод GetHashCode(IEqualityComparer), передавая компаратор для типа элементов в массив.

(Приведение необходимо, так как класс Array реализует метод явно.)

Например, если объект имеет int массив, то вы можете реализовать GetHashCode так:

public override int GetHashCode() 
{ 
    return ((IStructuralEquatable)this.array).GetHashCode(EqualityComparer<int>.Default); 
} 

В случае вам интересно, вот как класс массива реализует метод GetHashCode (от Reference Source):

internal static int CombineHashCodes(int h1, int h2) { 
    return (((h1 << 5) + h1)^h2); 
} 

int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) { 
    if (comparer == null) 
     throw new ArgumentNullException("comparer"); 
    Contract.EndContractBlock(); 

    int ret = 0; 

    for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) { 
     ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i))); 
    } 

    return ret; 
} 

Как вы можете видеть, текущая реализация использует только восемь последних элементов массива.

2

Я не согласен, вы должны естественным образом реализовать GetHashCode на массиве
Вы должны обновить его при каждом изменении
Или рассчитать его на лету
я сравнил бы прямо на лету
SequenceEquals будет использовать компаратор по умолчанию равенство, так что вы должны также осуществлять

public bool Equals 

0n объектов в массив

Enumerable.SequenceEqual
Имеет пример

public static void SequenceEqualEx1() 
{ 
    Pet pet1 = new Pet { Name = "Turbo", Age = 2 }; 
    Pet pet2 = new Pet { Name = "Peanut", Age = 8 }; 

    // Create two lists of pets. 
    List<Pet> pets1 = new List<Pet> { pet1, pet2 }; 
    List<Pet> pets2 = new List<Pet> { pet1, pet2 }; 

    bool equal = pets1.SequenceEqual(pets2); 

    Console.WriteLine(
     "The lists {0} equal.", 
     equal ? "are" : "are not"); 
} 
+2

OP реализовал Equals на объекте, который * содержит * массив. Естественно также реализовать GetHashCode на этом объекте. –

+0

@MichaelLiu Не так, как я его прочитал. Я не читаю объект, который * содержит * массив. Я прочитал его как объекты * в * массив переопределяет равно this.array [n] == otherObject.array [n]. – Paparazzi

+1

Почему у объекта * in * массив есть метод Equals, который ссылается на 'this.array'? Это означает, что у вас есть массив объектов, которые, в свою очередь, содержат массивы. –