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

ЖАНРЫ

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

// Использовать специальный конструктор

Car anotherMyCar = new Car("Honda", "Pilot", "Blue");

Console.WriteLine("Another variable for my car: ");

DisplayCarStats(anotherMyCar);

Console.WriteLine;

// Попытка изменения свойства приводит к ошибке на этапе компиляции.

// myCar.Color = "Red";

Console.ReadLine;

static void DisplayCarStats(Car c)

{

Console.WriteLine("Car Make: {0}", c.Make);

Console.WriteLine("Car Model: {0}", c.Model);

Console.WriteLine("Car Color: {0}", c.Color);

}

Вполне

ожидаемо оба метода создания объекта работают, значения свойств отображаются, а попытка изменить свойство после конструирования приводит к ошибке на этапе компиляции.

Чтобы создать тип записи

CarRecord
, добавьте к проекту новый файл по имени
CarRecord.cs
со следующим кодом:

record CarRecord

{

public string Make { get; init; }

public string Model { get; init; }

public string Color { get; init; }

public CarRecord {}

public CarRecord (string make, string model, string color)

{

Make = make;

Model = model;

Color = color;

}

}

Запустив приведенный далее код из

Program.cs
, вы можете удостовериться в том, что поведение записи
CarRecord
будет таким же, как у класса
Car
со средствами доступа только для инициализации:

Console.WriteLine("/*************** RECORDS *********************/");

// Использовать инициализацию объекта

CarRecord myCarRecord = new CarRecord

{

Make = "Honda",

Model = "Pilot",

Color = "Blue"

};

Console.WriteLine("My car: ");

DisplayCarRecordStats(myCarRecord);

Console.WriteLine;

// Использовать специальный конструктор

CarRecord anotherMyCarRecord = new CarRecord("Honda", "Pilot", "Blue");

Console.WriteLine("Another variable for my car: ");

Console.WriteLine(anotherMyCarRecord.ToString);

Console.WriteLine;

// Попытка изменения свойства приводит к ошибке на этапе компиляции.

// myCarRecord . Color = "Red";

Console.ReadLine;

Хотя мы пока еще не обсуждали эквивалентность (см. следующий раздел) или наследование (см. следующую главу) с типами записей, первое знакомство с записями не создает впечатления, что они обеспечивают большое преимущество. Текущий пример записи

CarRecord
включал весь ожидаемый связующий код. Заметное отличие присутствует в выводе: метод
ToString
для типов записей более причудлив, как видно в показанном ниже фрагменте вывода:

/*************** RECORDS *********************/

My car:

CarRecord { Make = Honda, Model = Pilot, Color = Blue }

Another variable for my car:

CarRecord { Make = Honda, Model = Pilot, Color = Blue }

Но взгляните на следующее обновленное определение записи

Car
:

record CarRecord(string Make, string Model, string Color);

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

Эквивалентность с типами записей

В примере класса

Car
два экземпляра
Car
создавались с одними и теми же данными. В приведенной далее проверке может показаться, что следующие два экземпляра класса эквивалентны:

Console.WriteLine($"Cars are the same? {myCar.Equals(anotherMyCar)}");

// Эквивалентны ли экземпляры Car?

Однако они не эквивалентны. Вспомните, что типы записей представляют собой специализированный вид класса, а классы являются ссылочными типами. Чтобы два ссылочных типа были эквивалентными, они должны указывать на тот же самый объект в памяти. В качестве дальнейшей проверки выясним, указывают ли два экземпляра

Car
на тот же самый объект:

Console.WriteLine($"Cars are the same reference?

{ReferenceEquals(myCar, anotherMyCar)}");

// Указывают ли экземпляры Car на тот же самый объект?

Запуск программы дает приведенный ниже результат:

Cars are the same? False

CarRecords are the same? False

Типы записей ведут себя по-другому. Они неявно переопределяют

Equals
,
==
и
!=
, чтобы производить результаты, как если бы экземпляры были типами значений. Взгляните на следующий код и показанные далее результаты:

Console.WriteLine($"CarRecords are the same?

{myCarRecord.Equals(anotherMyCarRecord)}");

// Эквивалентны ли экземпляры CarRecord?

Console.WriteLine($"CarRecords are the same reference?

{ReferenceEquals(myCarRecord,another
MyCarRecord)}");

// Указывают ли экземпляры CarRecord на тот же самый объект?

Console.WriteLine($"CarRecords are the same?

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