Книги онлайн и без регистрации » Разная литература » Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 76 77 78 79 80 81 82 83 84 ... 407
Перейти на страницу:
проходить по всем частям определения и заполнять необходимые детали. Испытайте описанный прием.

При определении автоматического свойства вы просто указываете модификатор доступа, лежащий в основе тип данных, имя свойства и пустые области get/set. Во время компиляции тип будет оснащен автоматически сгенерированным поддерживающим полем и подходящей реализацией логики get/set.

На заметку! Имя автоматически сгенерированного закрытого поддерживающего поля будет невидимым для вашей кодовой базы С#. Просмотреть его можно только с помощью инструмента вроде ildasm.exe.

Начиная с версии C# 6, разрешено определять "автоматическое свойство только для чтения", опуская область set. Автоматические свойства только для чтения можно устанавливать только в конструкторе. Тем не менее, определять свойство, предназначенное только для записи, нельзя. Вот пример:

// Свойство только для чтения? Допустимо!

public int MyReadOnlyProp { get; }

// Свойство только для записи? Ошибка!

public int MyWriteOnlyProp { set; }

Взаимодействие с автоматическими свойствами

Поскольку компилятор будет определять закрытые поддерживающие поля на этапе компиляции (и учитывая, что эти поля в коде C# непосредственно не доступны), в классе, который имеет автоматические свойства, для установки и чтения лежащих в их основе значений всегда должен применяться синтаксис свойств. Указанный факт важно отметить, т.к. многие программисты напрямую используют закрытые поля внутри определения класса, что в данном случае невозможно. Например, если бы класс Car содержал метод DisplayStats(), то в его реализации пришлось бы применять имена свойств:

class Car

{

   // Автоматические свойства!

   public string PetName { get; set; }

   public int Speed { get; set; }

   public string Color { get; set; }

   public void DisplayStats()

   {

     Console.WriteLine("Car Name: {0}", PetName);

     Console.WriteLine("Speed: {0}", Speed);

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

   }

}

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

using System;

using AutoProps;

Console.WriteLine("***** Fun with Automatic Properties *****n");

Car c = new Car();

c.PetName = "Frank";

c.Speed = 55;

c.Color = "Red";

Console.WriteLine("Your car is named {0}? That's odd...",

                   c.PetName);

c.DisplayStats();

Console.ReadLine();

Автоматические свойства и стандартные значения

Когда автоматические свойства применяются для инкапсуляции числовых и булевских данных, их можно использовать прямо внутри кодовой базы, т.к. скрытым поддерживающим полям будут присваиваться безопасные стандартные значения (false для булевских и 0 для числовых данных). Но имейте в виду, что когда синтаксис автоматического свойства применяется для упаковки переменной другого класса, то скрытое поле ссылочного типа также будет установлено в стандартное значение null (и это может привести к проблеме, если не проявить должную осторожность).

Добавьте к текущему проекту новый файл класса по имени Garage (представляющий гараж), в котором используются два автоматических свойства (разумеется, реальный класс гаража может поддерживать коллекцию объектов Car; однако в данный момент проигнорируем такую деталь):

namespace AutoProps

{

  class Garage

  {

     // Скрытое поддерживающее поле int установлено в О!

     public int NumberOfCars { get; set; }

     // Скрытое поддерживающее поле Car установлено в null!

     public Car MyAuto { get; set; }

  }

}

Имея стандартные значения C# для полей данных, значение NumberOfCars можно вывести в том виде, как есть (поскольку ему автоматически присвоено значение 0). Но если напрямую обратиться к MyAuto, то во время выполнения сгенерируется исключение ссылки на null, потому что лежащей в основе переменной-члену типа Car не был присвоен новый объект.

Garage g = new Garage();

// Нормально, выводится стандартное значение 0.

Console.WriteLine("Number of Cars: {0}", g.NumberOfCars);

// Ошибка во время выполнения!

// Поддерживающее поле в данный момент равно null!

Console.WriteLine(g.MyAuto.PetName);

Console.ReadLine();

Чтобы решить проблему, можно модифицировать конструкторы класса, обеспечив безопасное создание объекта. Ниже показан пример:

class Garage

{

   // Скрытое поддерживающее поле установлено в 0!

   public int NumberOfCars { get; set; }

   // Скрытое поддерживающее поле установлено в null!

   public Car MyAuto { get; set; }

   // Для переопределения стандартных значений, присвоенных скрытым

   // поддерживающим полям, должны использоваться конструкторы.

   public Garage()

   {

     MyAuto = new Car();

     NumberOfCars = 1;

   }

   public Garage(Car car, int number)

   {

     MyAuto = car;

     NumberOfCars = number;

   }

}

После такого изменения объект Car теперь можно помещать в объект Garage:

Console.WriteLine("***** Fun with Automatic Properties *****n");

// Создать объект автомобиля.

Car c = new Car();

c.PetName = "Frank";

c.Speed = 55;

c.Color = "Red";

c.DisplayStats();

// Поместить автомобиль в гараж.

Garage g = new Garage();

g.MyAuto = c;

// Вывести количество автомобилей в гараже

Console.WriteLine("Number of Cars in garage: {0}", g.NumberOfCars);

// Вывести название автомобиля.

Console.WriteLine("Your car is named: {0}", g.MyAuto.PetName);

Console.ReadLine();

Инициализация автоматических свойств

Наряду с тем, что предыдущий подход работает вполне нормально, в версии C# 6 появилась языковая возможность, которая содействует упрощению способа присваивания автоматическим свойствам их начальных значений. Как упоминалось ранее в главе, полю данных в классе можно напрямую присваивать начальное значение при его объявлении. Например:

class Car

{

  private int numberOfDoors = 2;

}

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

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

class Garage

1 ... 76 77 78 79 80 81 82 83 84 ... 407
Перейти на страницу:

Комментарии
Минимальная длина комментария - 20 знаков. В коментария нецензурная лексика и оскорбления ЗАПРЕЩЕНЫ! Уважайте себя и других!
Комментариев еще нет. Хотите быть первым?