При создании последней переменной Point специальный конструктор не используется (как делается традиционно), а взамен устанавливаются значения открытых свойств X и Y. "За кулисами" вызывается стандартный конструктор типа, за которым следует установка значений указанных свойств. В таком отношении синтаксис инициализации объектов представляет собой просто сокращение синтаксиса для создания переменной класса с применением стандартного конструктора и установки данных состояния свойство за свойством.
На заметку! Важно помнить о том, что процесс инициализации объектов неявно использует методы установки свойств. Если метод установки какого-то свойства помечен как private, тогда этот синтаксис применить не удастся.
Использование средства доступа только для инициализации (нововведение в версии 9.0)
В версии C# 9.0 появилось новое средство доступа только для инициализации. Оно позволяет устанавливать свойство во время инициализации, но после завершения конструирования объекта свойство становится доступным только для чтения. Свойства такого типа называются ReadOnlyPointAfterCreation.cs и поместите в него следующий код:
using System;
namespace ObjectInitializers
{
class PointReadOnlyAfterCreation
{
public int X { get; init; }
public int Y { get; init; }
public void DisplayStats()
{
Console.WriteLine("InitOnlySetter: [{0}, {1}]", X, Y);
}
public PointReadOnlyAfterCreation(int xVal, int yVal)
{
X = xVal;
Y = yVal;
}
public PointReadOnlyAfterCreation() { }
}
}
Новый класс тестируется с применением приведенного ниже кода:
// Создать объект точки, допускающий только чтение
// после конструирования
PointReadOnlyAfterCreation firstReadonlyPoint =
new PointReadOnlyAfterCreation(20, 20);
firstReadonlyPoint.DisplayStats();
// Или создать объект точки с использованием синтаксиса только
// для инициализации.
PointReadOnlyAfterCreation secondReadonlyPoint =
new PointReadOnlyAfterCreation { X = 30, Y = 30 };
secondReadonlyPoint.DisplayStats();
Обратите внимание, что в коде для класса Point ничего не изменилось кроме, разумеется, имени класса. Отличие в том, что после создания экземпляра класса модифицировать значения свойств X и Y нельзя. Например, показанный далее код не скомпилируется:
// Следующие две строки не скомпилируются
secondReadonlyPoint.X = 10;
secondReadonlyPoint.Y = 10;
Вызов специальных конструкторов с помощью синтаксиса инициализации
В предшествующих примерах объекты типа Point инициализировались путем неявного вызова стандартного конструктора этого типа:
// Здесь стандартный конструктор вызывается неявно.
Point finalPoint = new Point { X = 30, Y = 30 };
При желании стандартный конструктор допускается вызывать и явно:
// Здесь стандартный конструктор вызывается явно.
Point finalPoint = new Point() { X = 30, Y = 30 };
Имейте в виду, что при конструировании объекта типа с использованием синтаксиса инициализации можно вызывать любой конструктор, определенный в классе. В настоящий момент в типе Point определен конструктор с двумя аргументами для установки позиции (Point приведет к установке X в 100 и Y в 100 независимо от того факта, что в аргументах конструктора указаны значения 10 и 16:
// Вызов специального конструктора.
Point pt = new Point(10, 16) { X = 100, Y = 100 };