Инициализация частных членов c # - PullRequest
2 голосов
/ 03 февраля 2010

У меня есть два частных списка, которые нужно инициализировать при создании объекта. Второй список зависит от первого. Могу ли я сделать это так:

  public class MyClass
  {
      private List<T> myList = new List<T>();
      private ReadOnlyCollection<T> myReadOnlyList = myList.AsReadOnly;

      ...
  }

Второй список доступен только для чтения вокруг первого.

Можно ли ожидать, что c # будет выполнять эти две строки в этом порядке при каждом запуске?

Или я должен поместить эту инициализацию в конструктор?

Edit:
Извините за глупый вопрос. Я попробовал, и компилятор говорит:

Error   1   A field initializer cannot reference the 
             non-static field, method, or property...

Ответы [ 3 ]

12 голосов
/ 03 февраля 2010

Нет. Если вы хотите инициализировать переменную на основе отдельной переменной в классе, вам нужно сделать это в конструкторе:

public class MyClass 
{ 
    private List<T> myList = new List<T>(); 
    private ReadOnlyCollection<T> myReadOnlyList;
    public MyClass()
    {
        myReadOnlyList = myList.AsReadOnly; 
    }

} 

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

4 голосов
/ 03 февраля 2010

Можно ли ожидать, что c # будет выполнять эти две строки в этом порядке при каждом запуске?

Да, инициализаторы переменных экземпляра, когда они разрешены (см. Ниже), запускаются в порядке их появления. Я отсылаю вас к §10.11.2 спецификации:

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

Однако инициализатор поля не может ссылаться на нестатическое поле, как вы это сделали. Ваш код не является законным. Это §10.5.5.2 спецификации:

Инициализатор переменной для поля экземпляра не может ссылаться на создаваемый экземпляр. Таким образом, это ошибка времени компиляции, чтобы ссылаться на это в инициализаторе переменной, так как это ошибка времени компиляции для инициализатора переменной, чтобы ссылаться на любой элемент экземпляра через простое имя.

Относительно вашего второго вопроса:

Или я должен поместить эту инициализацию в конструктор?

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

Последнее замечание по отдельному вопросу. Даже следующее не является законным:

public class MyClass {
    private List<T> myList;public class MyClass
    private ReadOnlyCollection<T> myReadOnlyList;
    public MyClass() { 
        myList = new List<T>();
        myReadOnlyList = myList.AsReadOnly;

}

Это потому, что вы не объявили MyClass как универсальный класс. Заменить public class MyClass на public class MyClass<T>.

1 голос
/ 03 февраля 2010

Да, вы должны поместить инициализацию myReadOnlyList в конструктор, но для согласованности мои рекомендации поместили оба в конструктор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...