C# - Вычисление GetHashCode
Есть вопрос по работе метода GetHashCode
. Читаю вроде как полезную книжку по C#, но об одном нюансе (который я не понимаю?) там не написано. Есть вот такой вот код:
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string SSN { get; set; } = "";
public int Age { get; set; }
public Person(string firstName, string lastName, int age)
{
FirstName = firstName;
LastName = lastName;
Age = age;
}
public Person() { }
public override string ToString() => $"[First name: {FirstName}; Second name: {LastName}; Age: {Age}]";
public override bool Equals(object? obj) => obj?.ToString() == this.ToString() ;
// public override int GetHashCode() => this.ToString().GetHashCode() ;
}
Здесь я переопределяю "стандартный" (?) метод GetHashCode
из System.Object
под свой класс, который считает хэш на основе строкового представления состояний объекта.
Запускаем следующий код (моя реализация закомменчена, отрабатывает "дефолтный" GetHashCode
):
Person Bernard = new Person("Bernard", "Cloud", 29);
Person Kyle = new Person("Bernard", "Cloud", 29);
Console.WriteLine(Bernard.ToString());
Console.WriteLine(Kyle.ToString());
Console.WriteLine(Bernard.Equals(Kyle)); // output: True => хэш должен быть одинаковый?
Console.WriteLine(Bernard.GetHashCode());
Console.WriteLine(Kyle.GetHashCode());
И видим, что хэши отличаются. У меня 2 вопроса.
Почему в моей реализации
GetHashCode
каждый раз генерируются новые хэши при перезапуске программы.Почему при вызове стандартного
GetHashCode
хэши получаются разные, причем не изменяются при перезапуске.
У меня есть какие-то догадки, но это все смешалось в кашу. В моей реализации, я так понимаю, хэш вычисляется на основе состояний объекта (полей) и соответственно выводит либо равные, либо отличающиеся хэши.
А при перезапуске они меняются потому, что значение еще и зависит от того, где именно в памяти лежат объекты. А т.к. в C# автоматический сборщик мусора, при завершении экземпляры удаляются, а при запуске для них выделяется новая память.
Со стандартной реализацией вообще ничего не ясно. Почему хэши отличаются, может, и понятно: они считаются другим образом, не на основе строкового представления (как у меня)? А вот почему они еще и не изменяются при перезапуске программы.
Вообще, в моей реализации хэш считается для обычной строки string
, в дефолтной "на вход" уже поступает object
, а именно, экземпляр Person
. Тут я подумал в разнице между типами и тем, как под них выделяется память, но вроде как это все относится к одному и тому же "Reference Types".