Свойства private-setter в инициализации объекта С# 3.0

Если у меня есть следующий код:

public class MyClass 
{ 
  public string myName { get; private set; } 
  public string myId { get; set; } 
} 

Для установщика создается частная генерируемая компилятором переменная. Я хочу, чтобы сеттер не был доступен только для инициализации объекта. Но как я могу сначала установить переменную myName?

Чтение об инициализации объекта Я обнаружил следующее:

... его только для чтения и частное поле, представляющее базовое хранилище имеет имя, сгенерированное компилятором, которое мы не может использоваться в конструкторе для назначения к нему. Решение состоит в использовании объекта [...] инициализаторы

Таким образом, было бы полезно использовать:

MyClass mc = new MyClass { 
myName = "What ever", 
myId = "1234" 
};

Но это в ошибке компилятора говорит, что:

Свойство или индекс 'MyClass.MyClass.myName' не могут использоваться в этом контексте, потому что доступный доступ к набору недоступен

Итак, есть ли способ достичь этого значения с помощью инициализации объекта? Если есть, то каков правильный способ сделать это?

Ответ 1

Частный набор myName означает, что вы можете только инициализировать (установить) его из того, что является членом MyClass. Например:

        public class MyClass {
        public string myName { get; private set; }
        public string myId { get; set; }

        public static MyClass GetSampleObject() {
            MyClass mc = new MyClass
            {
                myName = "Whatever",
                myId = "1234"
            };
            return mc;
        }
    }

(Я скопировал и вставил ваш код инициализации в метод GetSampleObject).

Но если вы попытаетесь установить его вне MyClass, вы получите ошибку компилятора, так как private является закрытым.

Ответ 2

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

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

Ответ 3

Если они должны быть установлены при инициализации, рассмотрите возможность передать их в качестве аргументов конструктору

Ответ 4

У меня было это требование в прошлом, а также для вещей OR/M. То, что я в основном делаю, это использовать реальное свойство с помощью поля поддержки и проверить, установлено ли свойство уже. Если да, добавьте исключение.

public string myName
{
    get{ return _myName; }
    set
    {
        if( _myName != null && _myName != value )
            throw new Exception( "The myName property may only be set once." );
        _myName = value;
    }
}

private string _myName;

И еще один вариант совместимости с OR/M, который также использует инициализацию конструктора:

public class MyClass 
{ 
    [Obsolete( "For ORM use only!" )] 
    [EditorBrowsableState( EditorBrowsableState.Never )]
    public MyClass(){}

    public MyClass( string name ){ myName = name; }

    public string myName { get; private set; } 
    public string myId { get; set; } 
}