Второй специальный конструктор не может быть преобразован в выражение, т.к. члены, сжатые до выражений, должны быть однострочными методами.
Конструкторы с параметрами 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;
// Новые члены для представления имени водителя.
public string name;
public void SetDriverName(string name) => name = name;
...
}
Хотя приведенный код нормально скомпилируется, компилятор C# выдаст сообщение с предупреждением о том, что переменная присваивается сама себе! В целях иллюстрации добавьте в свой код вызов метода
SetDriverName
и обеспечьте вывод значения поля name. Вы можете быть удивлены, обнаружив, что значением поля name является пустая строка!
// Создать объект Motorcycle с мотоциклистом по имени Tiny?
Motorcycle c = new Motorcycle(5);
c.SetDriverName("Tiny");
c.PopAWheely;
Console.WriteLine("Rider name is {0}", c.name); // Выводит пустое значение name!
Проблема в том, что реализация метода
SetDriverName
присваивает входному параметру значение его самого, т.к. компилятор предполагает, что
name
ссылается на переменную, находящуюся в области видимости метода, а не на поле
name
из области видимости класса. Для информирования компилятора о том, что необходимо установить поле данных
name
текущего объекта в значение входного параметра name, просто используйте ключевое слово