Looking for c# Keywords? Try Ask4Keywords

C# Language Инициализаторы автоистории


пример

Вступление

Свойства можно инициализировать с помощью оператора = после закрытия } . В приведенном ниже разделе « Coordinate » показаны доступные параметры инициализации свойства:

6,0
public class Coordinate
{ 
    public int X { get; set; } = 34; // get or set auto-property with initializer

    public int Y { get; } = 89;      // read-only auto-property with initializer              
}

Аксессоры с различной видимостью

Вы можете инициализировать автоматические свойства, которые имеют различную видимость для их аксессуаров. Вот пример с защищенным сеттером:

    public string Name { get; protected set; } = "Cheeze";

Аксессор также может быть internal , internal protected или private .


Свойства только для чтения

Помимо гибкости с видимостью, вы также можете инициализировать автоматические свойства только для чтения. Вот пример:

    public List<string> Ingredients { get; } = 
        new List<string> { "dough", "sauce", "cheese" };

В этом примере также показано, как инициализировать свойство сложным типом. Кроме того, авто-свойства не могут быть только для записи, поэтому также исключает инициализацию только для записи.


Старый стиль (pre C # 6.0)

До C # 6 это требовало гораздо более подробного кода. Мы использовали одну дополнительную переменную, называемую свойство backing для свойства, чтобы присвоить значение по умолчанию или инициализировать публичное свойство, как показано ниже,

6,0
public class Coordinate
{
    private int _x = 34;
    public int X { get { return _x; } set { _x = value; } }

    private readonly int _y = 89;
    public int Y { get { return _y; } }
    
    private readonly int _z;
    public int Z { get { return _z; } }

    public Coordinate()
    {
        _z = 42;
    }
}

Примечание. До C # 6.0 вы все равно можете инициализировать чтение и запись автоматически реализованных свойств (свойств с помощью getter и setter) внутри конструктора, но вы не можете инициализировать свойство inline с его объявлением

Посмотреть демо


использование

Инициализаторы должны оценивать статические выражения, как и инициализаторы полей. Если вам нужно ссылаться на нестатические элементы, вы можете либо инициализировать свойства в конструкторах, как раньше, либо использовать свойства с выражением. Нестатические выражения, подобные приведенным ниже (закомментированные), генерируют ошибку компилятора:

// public decimal X { get; set; } = InitMe();  // generates compiler error

decimal InitMe() { return 4m; }

Но статические методы могут использоваться для инициализации автоматических свойств:

public class Rectangle
{
    public double Length { get; set; } = 1;
    public double Width { get; set; } = 1;
    public double Area { get; set; } = CalculateArea(1, 1);

    public static double CalculateArea(double length, double width)
    {
        return length * width;
    }
}

Этот метод также можно применять к свойствам с различным уровнем доступа:

public short Type { get; private set; } = 15;

Инициализатор автоматического свойства позволяет присваивать свойства непосредственно в объявлении. Для свойств только для чтения он выполняет все требования, необходимые для обеспечения неизменности свойства. Рассмотрим, например, класс FingerPrint в следующем примере:

public class FingerPrint
{
  public DateTime TimeStamp { get; } = DateTime.UtcNow;

  public string User { get; } =
    System.Security.Principal.WindowsPrincipal.Current.Identity.Name;

  public string Process { get; } =
    System.Diagnostics.Process.GetCurrentProcess().ProcessName;
}

Посмотреть демо


Предупреждающие примечания

Постарайтесь не путать инициализаторы авто-свойств или поля с похожими способами выражения-тела, которые используют => в противоположность = , и поля, которые не включают { get; } .

Например, каждая из следующих деклараций различна.

public class UserGroupDto
{
    // Read-only auto-property with initializer:       
    public ICollection<UserDto> Users1 { get; } = new HashSet<UserDto>();
    
    // Read-write field with initializer:
    public ICollection<UserDto> Users2 = new HashSet<UserDto>();

    // Read-only auto-property with expression body:
    public ICollection<UserDto> Users3 => new HashSet<UserDto>();
}

Отсутствует { get; } в объявлении свойства приводит к публичному полю. И автообновление Users1 чтения, и поле чтения-записи Users2 инициализируются только один раз, но общедоступное поле позволяет изменять экземпляр коллекции вне класса, что обычно нежелательно. Изменение автоматического свойства только для чтения с телом выражения в свойство только для чтения с инициализатором требует не только удаления > from => , но и добавления { get; } .

Users3 символ ( => вместо = ) в Users3 приводит к каждому доступу к свойству, возвращающему новый экземпляр HashSet<UserDto> который, хотя действительный C # (с точки зрения компилятора) вряд ли будет желательным, когда используется для члена коллекции.

Вышеприведенный код эквивалентен:

public class UserGroupDto
{
    // This is a property returning the same instance
    // which was created when the UserGroupDto was instantiated.
    private ICollection<UserDto> _users1 = new HashSet<UserDto>();
    public ICollection<UserDto> Users1 { get { return _users1; } }

    // This is a field returning the same instance
    // which was created when the UserGroupDto was instantiated.
    public virtual ICollection<UserDto> Users2 = new HashSet<UserDto>();

    // This is a property which returns a new HashSet<UserDto> as
    // an ICollection<UserDto> on each call to it.
    public ICollection<UserDto> Users3 { get { return new HashSet<UserDto>(); } }
}