Автоматическое свойство только с геттером, может быть установлено, почему?


Я создал автоматическое свойство:

public int Foo { get; } 

это только добытчик. Но когда я строю конструктор, я могу изменить значение:

public MyClass(string name)
{
    Foo = 5;
}

почему это возможно, даже если это get-only?

6 72

6 ответов:

Это новая функция C# 6, "авто-свойства только для геттеров", также известная как" инициализаторы авто-свойств для свойств только для чтения", как описано в этом статья журнала MSDN "C#: новый и улучшенный C# 6.0" от Марка Михаэлиса и C# 6.0 draft Language Specification.

сеттер поля только для чтения доступен только в конструкторе, во всех других сценариях поле по-прежнему доступно только для чтения и ведет себя как раньше.

Это удобный синтаксис для уменьшения объема кода, который необходимо ввести, и для устранения необходимости явного объявления частной переменной уровня модуля для хранения значения.

эта функция считалась столь же важной, поскольку с введением автоматически реализованных свойств в C#3 изменяемые свойства (те, у которых есть геттер и сеттер) стали быстрее писать, чем неизменяемые (те, у которых есть только геттер), то есть люди испытывали соблазн использовать изменяемые свойства, чтобы избежать необходимости вводить текст. код для резервного поля обычно требуется для свойств только для чтения. Существует больше обсуждения автоматически реализованных свойств в соответствующий раздел руководства по программированию Microsoft C#.

это сообщение в блоге, "#1,207-C# 6.0-авто-инициализаторы свойств только для чтения " Шон Секстон есть хорошее объяснение и пример следующим образом:

до C# 6.0, если вам нужно свойство только для чтения (неизменяемое), вы бы обычно используется резервное поле только для чтения, которое инициализируется в конструктор, как показано ниже.

public class Dog 
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    private readonly DateTime creTime;
    public DateTime DogCreationTime 
    {
        get { return creTime; }
    }

    public Dog(string name)
    {
        Name = name;
        creTime = DateTime.Now;
    }
}

В C# 6.0 можно использовать автоматически реализованные свойства для реализации свойство только для чтения. Это можно сделать с помощью автоматического свойства инициализатор. Результат намного чище, чем в приведенном выше примере, где мы должны были явно объявить резервное поле.

public class Dog
{
    public string Name { get; set; }

    // DogCreationTime is immutable
    public DateTime DogCreationTime { get; } = DateTime.Now;

    public Dog(string name)
    {
        Name = name;
    }
}

более подробную информацию можно найти в РЕПО dotnet Roslyn on GitHub:

авто-свойства теперь могут быть объявлены без сеттера.

резервное поле авто-свойства только для геттера неявно объявлено как readonly (хотя это имеет значение только для отражения нужда.) Он может быть инициализирован через инициализатор на свойство, как в примере выше. Кроме того, свойство только для геттера может быть присваивается в теле конструктора типа объявления, что вызывает значение, которое будет присвоено непосредственно основное поле:

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

и в C# 6.0 draft Language Specification:

автоматически реализуемые свойства

автоматически реализованное свойство (или авто-свойство для краткости), является неабстрактное свойство non-extern с доступом только через точку с запятой тела. Авто-свойства должны иметь доступ get и могут дополнительно есть набор аксессуаров.

если свойство задано как автоматически реализуемое свойство, скрытая поддержка поле автоматически доступно для объекта недвижимости, и аксессоры реализованы для чтения и записи в это резервное поле. Если у авто-свойства нет заданного метода доступа, то резервное копирование поле считается только для чтения (Readonly fields). Как только для чтения поле, авто-свойство только для геттера также может быть назначено в теле конструктора включающего класса. Такое назначение присваивает непосредственно на резервное поле только для чтения свойства.

авто-собственность может дополнительно иметь property_initializer, который является применяется непосредственно к резервному полю в качестве variable_initializer (Инициализаторы переменных).

Это новая функция в C#6 это позволяет создавать свойства только для чтения и инициализировать их значения из конструктора (или встроенного при их объявлении).

Если вы попытаетесь изменить значение этого свойства вне конструктора, это даст вам ошибку при компиляции.

Он доступен только для чтения в том смысле, что после инициализации его значения (встроенного или внутри конструктора) вы не можете изменить его значение.

если бы не было возможности инициализировать свойство только для чтения из конструктора (или инициализатора автоматического свойства), то это было бы бесполезно, так как оно всегда возвращало бы значение по умолчанию для своего типа (0 для цифр, null для ссылочных типов). Та же семантика применяется к только для чтения поля во всех версиях C#.

чтобы определить свойство true getter-only (которое не может быть инициализировано из конструктора), необходимо указать, что оно возвращает как часть определение:

public int Foo { get { return 5; } }

или, более кратко В C# 6:

public int Foo => 5;

функция автоматического свойства была добавлена в язык во время выпуска C# 3.0. Он позволяет определить свойство без какого-либо резервного поля, однако вам все равно нужно использовать конструктор для инициализации этих автоматических свойств до значения, отличного от значения по умолчанию. C# 6.0 вводит новую функцию, называемую Auto property initializer, которая позволяет инициализировать эти свойства без конструктора, как показано ниже:

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

public class MyClass
{
    public int Foo { get; }

    public Foo(int foo)
    {
        Foo = foo;
    }
}

теперь в C# 6.0 появилась возможность использовать инициализатор с авто-свойством означает, что явный код конструктора не требуется.

public string Foo { get; } = "SomeString";

public List<string> Genres { get; } = new List<string> { "Comedy", "Drama" };

вы можете найти более подробную информацию об этом здесь

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

прежде всего я хочу уточнить, что свойство нравится

public string FirstName { get; }

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

чтобы убедиться в этом, вы можете запустить и проверить приведенный выше код с помощью Visual Studio. Если вы измените версию языка С C#6.0 на C#5.0, компилятор выдаст следующее исключение функция только для чтения автоматически реализуемые свойства не доступно в C# 5. Пожалуйста, используйте язык версии 6 или выше.

чтобы изменить версию языка C# посетите здесь

теперь я подхожу к вашему второму вопросу

"это только добытчик. Но когда я строю конструктор, я могу изменить значение"

Microsoft вводит "только для чтения автоматически реализуемые свойства" на логике только для чтения. Как мы знаем, ключевое слово "readonly" доступно из C#1.0. мы используем "только для чтения" ключевое слово как модификатор на поле, и это поле может быть назначено в 2 способ или на момент объявления или в конструкторе того же класса.

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

Way1 (на момент объявления):

public string FirstName { get; } = "Banketeshvar";

Way2 (в конструкторе в том же класс)

Person()
{
 FirstName  = "Banketeshvar";
}

Чисто ReadOnly Свойство

если вы ищете чисто Readonly свойство, то пойти на это

public string FullName => "Manish Sharma";

теперь вы не можете присвоить значение свойства "FullName" из конструктора. Если вы попытаетесь сделать это, он выдаст следующие исключения

"свойство или индексатор 'человека.FullName 'не может быть присвоено -- это только для чтения"

переменная, объявленная readonly может быть записано в конструкторе, но в языках, которые соблюдают атрибут, не может быть изменен после возврата конструктора. Этот квалификатор был предоставлен в качестве языковой функции, поскольку он часто необходим для полей, значения которых будут меняться в зависимости от параметров конструктора (то есть они не могут быть инициализированы до запуска конструктора), но не должны изменяться после возврата конструкторов, но он был доступен только для переменных, представленных в виде полей. Этот семантика readonly-квалифицированные поля во многих случаях были бы идеальны для открытых членов, за исключением того, что для классов часто лучше предоставлять члены-даже неизменяемые-как свойства, а не поля.

так же, как существуют авто-свойства для чтения и записи, позволяющие классам предоставлять изменяемые свойства так же легко, как обычные поля, существуют авто-свойства только для чтения, позволяющие классам предоставлять неизменяемые свойства так же легко, как readonly-квалифицированный поля. Так же, как readonly-квалифицированный поля могут быть записаны в конструкторе, так же и с get-only свойствами.