Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
class Car
{
// 'Состояние' объекта Car.
public string petName;
public int currSpeed;
// Специальный стандартный конструктор.
public Car()
{
petName = "Chuck";
currSpeed = 10;
}
// Здесь currSpeed получает стандартное значение для типа int (0).
public Car(string pn)
{
petName = pn;
}
// Позволяет вызывающему коду установить полное состояние объекта Car.
public Car(string pn, int cs)
{
petName = pn;
currSpeed = cs;
}
...
}
Имейте в виду, что один конструктор отличается от другого (с точки зрения компилятора С#) числом и/или типами аргументов. Вспомните из главы 4, что определение метода с тем же самым именем, но разным количеством или типами аргументов, называется перегрузкой метода. Таким образом, конструктор класса Car перегружен, чтобы предложить несколько способов создания объекта во время объявления. В любом случае теперь есть возможность создавать объекты Car, используя любой из его открытых конструкторов. Вот пример:
Console.WriteLine("***** Fun with Class Types *****n");
// Создать объект Car по имени Chuck со скоростью 10 миль в час.
Car chuck = new Car();
chuck.PrintState();
// Создать объект Car по имени Mary со скоростью 0 миль в час.
Car mary = new Car("Mary");
mary.PrintState();
// Создать объект Car по имени Daisy со скоростью 75 миль в час.
Car daisy = new Car("Daisy", 75);
daisy.PrintState();
...
Конструкторы в виде членов, сжатых до выражений (нововведение в версии 7.0)
В C# 7 появились дополнительные случаи употребления для стиля членов, сжатых до выражений. Теперь такой синтаксис применим к конструкторам, финализаторам, а также к средствам доступа get/set для свойств и индексаторов. С учетом сказанного предыдущий конструктор можно переписать следующим образом:
// Здесь currSpeed получит стандартное
// значение для типа int (0).
public Car(string pn) => petName = pn;
Второй специальный конструктор не может быть преобразован в выражение, т.к. члены, сжатые до выражений, должны быть однострочными методами.
Конструкторы с параметрами out (нововведение в версии 7.3)
Начиная с версии C# 7.3, в конструкторах (а также в рассматриваемых позже инициализаторах полей и свойств) могут использоваться параметры out. В качестве простого примера добавьте в класс Car следующий конструктор:
public Car(string pn, int cs, out bool inDanger)
{
petName = pn;
currSpeed = cs;
if (cs > 100)
{
inDanger = true;
}
else
{
inDanger = false;
}
}
Как обычно, должны соблюдаться все правила, касающиеся параметров out. В приведенном примере параметру inDanger потребуется присвоить значение до завершения конструктора.
Еще раз о стандартном конструкторе
Как вы только что узнали, все классы снабжаются стандартным конструктором. Добавьте в свой проект новый файл по имени Motorcycle.cs с показанным ниже определением класса Motorcycle:
using System;
namespace SimpleClassExample
{
class Motorcycle
{
public void PopAWheely()
{
Console.WriteLine("Yeeeeeee Haaaaaeewww!");
}
}
}
Теперь появилась возможность создания экземпляров Motorcycle с помощью стандартного конструктора:
Console.WriteLine("***** Fun with Class Types *****n");
Motorcycle mc = new Motorcycle();
mc.PopAWheely();
...
Тем не менее, как только определен специальный конструктор с любым числом параметров, стандартный конструктор молча удаляется из класса и перестает быть доступным. Воспринимайте это так: если вы не определили специальный конструктор, тогда компилятор C# снабжает класс стандартным конструктором, давая возможность пользователю размещать в памяти экземпляр вашего класса с набором полей данных, которые установлены в корректные стандартные значения. Однако когда вы определяете уникальный конструктор, то компилятор предполагает, что вы решили взять власть в свои руки.
Следовательно, если вы хотите позволить пользователю создавать экземпляр вашего типа с помощью стандартного конструктора, а также специального конструктора, то должны явно переопределить стандартный конструктор. Важно понимать, что в подавляющем большинстве случаев реализация стандартного конструктора класса намеренно оставляется пустой, т.к. требуется только создание объекта со стандартными значениями. Обновите класс Motorcycle:
class Motorcycle
{
public int driverIntensity;
public void PopAWheely()
{
for (int i = 0; i <= driverIntensity; i++)
{
Console.WriteLine("Yeeeeeee Haaaaaeewww!");
}
}
// Вернуть стандартный конструктор, который будет.
// устанавливать все члены данных в стандартные значения
public Motorcycle() {}
// Специальный конструктор.
public Motorcycle(int intensity)
{
driverIntensity = intensity;
}
}
На заметку! Теперь, когда вы лучше понимаете роль конструкторов класса, полезно узнать об одном удобном сокращении. В Visual Studio и Visual Studio Code предлагается фрагмент кода ctor. Если вы наберете ctor и нажмете клавишу <ТаЬ>, тогда IDE-среда автоматически определит специальный стандартный конструктор. Затем можно добавить нужные параметры и логику реализации. Испытайте такой прием.
Роль ключевого слова this
В языке C# имеется ключевое слово this, которое обеспечивает доступ к текущему экземпляру класса. Один из возможных сценариев использования this предусматривает устранение неоднозначности с областью видимости, которая может возникнуть, когда входной параметр имеет такое же имя, как и поле данных класса. Разумеется, вы могли бы просто придерживаться соглашения об именовании, которое не приводит к такой неоднозначности; тем не менее, чтобы проиллюстрировать такой сценарий, добавьте в класс Motorcycle новое поле типа string (под названием name), предназначенное для представления имени водителя. Затем добавьте метод SetDriverName() со следующей реализацией:
class Motorcycle
{
public int driverIntensity;
//