Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

obj.GetHashCode = -564053045

Первым делом обратите внимание в примере на то, что объект

myCar
имеет тип
<>f__AnonymousType0`3
(в вашем выводе имя типа может быть другим). Помните, что имя, назначаемое типу, полностью определяется компилятором и не доступно в коде C# напрямую.

Пожалуй, наиболее важно здесь то, что каждая пара "имя-значение", определенная с использованием синтаксиса инициализации объектов, отображается на идентично именованное свойство, доступное только для чтения, и соответствующее закрытое поддерживающее поле, которое допускает только инициализацию. Приведенный ниже код C# приблизительно

отражает сгенерированный компилятором класс, применяемый для представления объекта
myCar
(его можно просмотреть посредством утилиты
ildasm.exe
):

private sealed class <>f__AnonymousType0'3'<'<Color>j__TPar',

'<Make>j__TPar', <CurrentSpeed>j__TPar>'

extends [System.Runtime][System.Object]

{

// Поля только для инициализации.

private initonly <Color>j__TPar <Color>i__Field;

private initonly <CurrentSpeed>j__TPar <CurrentSpeed>i__Field;

private initonly <Make>j__TPar <Make>i__Field;

// Стандартный конструктор.

public <>f__AnonymousType0(<Color>j__TPar Color,

<Make>j__TPar Make, <CurrentSpeed>j__TPar CurrentSpeed);

// Переопределенные методы.

public override bool Equals(object value);

public override int GetHashCode;

public override string ToString;

// Свойства только для чтения.

<Color>j__TPar Color { get; }

<CurrentSpeed>j__TPar CurrentSpeed { get; }

<Make>j__TPar Make { get; }

}

Реализация методов ToString и GetHashCode

Все анонимные типы автоматически являются производными от

System.Object
и предоставляют переопределенные версии методов
Equals
,
GetHashCode
и
ToString
. Реализация
ToString
просто строит строку из пар "имя-значение". Вот пример:

public override string ToString

{

StringBuilder builder = new StringBuilder;

builder.Append("{ Color = ");

builder.Append(this.<Color>i__Field);

builder.Append(", Make = ");

builder.Append(this.<Make>i__Field);

builder.Append(", CurrentSpeed = ");

builder.Append(this.<CurrentSpeed>i__Field);

builder.Append(" }");

return builder.ToString;

}

Реализация

GetHashCode
вычисляет хеш-значение, используя каждую переменную-член анонимного типа в качестве входных данных для типа
System.Collections.Generic.EqualityComparer<T>
.
С такой реализацией
GetHashCode
два анонимных типа будут выдавать одинаковые хеш-значения тогда (и только тогда), когда они обладают одним и тем же набором свойств, которым присвоены те же самые значения. Благодаря подобной реализации анонимные типы хорошо подходят для помещения внутрь контейнера
Hashtable
.

Семантика эквивалентности анонимных типов

Наряду с тем, что реализация переопределенных методов

ToString
и
GetHashCode
прямолинейна, вас может интересовать, как был реализован метод
Equals
. Например, если определены две переменные "анонимных автомобилей" с одинаковыми наборами пар "имя-значение", то должны ли эти переменные считаться эквивалентными? Чтобы увидеть результат такого сравнения, дополните класс
Program
следующим новым методом:

static void EqualityTest

{

// Создать два анонимных класса с идентичными наборами

// пар "имя-значение".

var firstCar = new { Color = "Bright Pink", Make = "Saab",

CurrentSpeed = 55 };

var secondCar = new { Color = "Bright Pink", Make = "Saab",

CurrentSpeed = 55 };

// Считаются ли они эквивалентными, когда используется Equals?

if (firstCar.Equals(secondCar))

{

Console.WriteLine("Same anonymous object!");

// Тот же самый анонимный объект

}

else

{

Console.WriteLine("Not the same anonymous object!");

// He тот же самый анонимный объект

}

// Можно ли проверить их эквивалентность с помощью операции ==?

if (firstCar == secondCar)

{

Console.WriteLine("Same anonymous object!");

// Тот же самый анонимный объект

}

else

{

Console.WriteLine("Not the same anonymous object!");

// He тот же самый анонимный объект

}

// Имеют ли эти объекты в основе один и тот же тип?

if (firstCar.GetType.Name == secondCar.GetType.Name)

{

Console.WriteLine("We are both the same type!");

// Оба объекта имеют тот же самый тип

}

else

{

Console.WriteLine("We are different types!");

// Объекты относятся к разным типам

}

// Отобразить все детали.

Поделиться с друзьями: