Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
Шрифт:
Интервал:
Закладка:
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 не был присвоен новый объект.
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})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;
// Вывести количество автомобилей в гараже