Какой код выполняется в GetHashCode для созданного мной класса?

105
12 июля 2021, 15:40

Пришлите, пожалуйста, ссылку на исходный код .net framework, где работает GetHashCode для объявленного мной класса.

Поиск по исходникам на referencesource.microsoft.com не приносит ровным счетом ничего по задаче, поскольку у System.Object GetHashCode объявлен с extern и не имеет реализации:

[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern int GetHashCode(Object o);

Где находится реализация такого метода?

Answer 1

Для запрета переопределения функции есть ключевое слово sealed, пример

public class MyClass
{
    public sealed override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

В таком случае наследники не смогут его переопределить

public class MyClassExt : MyClass
{
    public override int GetHashCode() // ошибка!
    {
        return base.GetHashCode();
    }
}
Answer 2

Стандартная реализация GetHashCode для object возвращает значение, генерируемое отдельно для каждого объекта, и никак не зависит от значений его полей (т.е., его использование при сравнении эквивалентно сравнению по ссылке). Так как он реализован в CLR, исходников GetHashCode из .NET Framework нет в официальных источниках. Реализацию GetHashCode из .NET Core можно посмотреть в исходниках CoreCLR (C++). Для этого нужно сначала найти соответствующий неуправляемый метод в файле coreclr/src/vm/ecalllist.h. Для RuntimeHelpers.GetHashCode это ObjectNative::GetHashCode:

FCFuncElement("GetHashCode", ObjectNative::GetHashCode)

Если дойти до получения самого значения, то это будет метод Thread.GetNewHashCode:

inline DWORD GetNewHashCode()
{
    LIMITED_METHOD_CONTRACT;
    // Every thread has its own generator for hash codes so that we won't get into a situation
    // where two threads consistently give out the same hash codes.
    // Choice of multiplier guarantees period of 2**32 - see Knuth Vol 2 p16 (3.2.1.2 Theorem A).
    DWORD multiplier = GetThreadId()*4 + 5;
    m_dwHashCodeSeed = m_dwHashCodeSeed*multiplier + 1;
    return m_dwHashCodeSeed;
}

То же самое в исходниках .NET Framework CLR, из неофициальных источников.

Таким образом, если нужен пример вычисления хэш-кода для своего типа, исходный код object.GetHashCode бесполезен. В качестве примера реализации вычисления хэш-кода на основе полей объекта вместо него можно взять например код генератора метода GetHashCode для анонимных типов из исходников компилятора C#.

READ ALSO
Записать данные в массив String

Записать данные в массив String

За один прогон с файла читается сразу 13 элементов (столбцов)

96
DateTime при выборе столбца меняется возраст

DateTime при выборе столбца меняется возраст

Есть два столбца, в столбце Год рождения, когда устанавливается дата то в столбце Возраст на: возраст меняетсяПодскажите пожалуйста, как...

95
Сравнение BigInteger и int, short в C#

Сравнение BigInteger и int, short в C#

Пытаюсь разобраться в принципе работы

86
Целесообразность класса для работы с БД MSSQL

Целесообразность класса для работы с БД MSSQL

Создал специальный вспомогательный класс для соединения и работы с БД

70