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 появилась языковая возможность, которая содействует упрощению способа присваивания автоматическим свойствам их начальных значений. Как упоминалось ранее в главе, полю данных в классе можно напрямую присваивать начальное значение при его объявлении. Например: