Подтвердить что ты не робот

Почему С# не разрешает инициализатор поля с нестатическими полями?

Почему С# разрешит это:

public class MyClass
{
  static int A=1;
  static int B=A+1;
}

Но не позволит ( "Инициализатор поля не может ссылаться на нестатические поля, метод или свойство" ) this

public class MyClass
{
   int A=1;
   int B=A+1;
}

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

public class MyClass
{
   int A=((Func<int>)(delegate(){ Console.WriteLine ("A"); return 1;}))();
   int B=((Func<int>)(delegate(){ Console.WriteLine ("B"); return 2;}))();
   int C=((Func<int>)(delegate(){ Console.WriteLine ("C"); return 3;}))();
}

void Main()
{
 var a = new MyClass();
}

Результат:

A
B
C

Вопрос

Меня больше интересует причина/логика, почему он был ограничен. просто для любопытства.

nb не нашел дубликата.

4b9b3361

Ответ 1

Меня больше интересует причина/логика, почему он был ограничен. просто для любопытства.

Если вы читаете С# Language Spec, 10.11.3, он намекает на обоснование здесь. При обсуждении переменных инициализаторов:

Полезно подумать об инициализаторах переменных экземпляра и инициализаторах конструктора в качестве операторов, которые автоматически вставляются перед телом-конструктором.

Поскольку они "вставлены перед конструктором", они выполняются до того, как this будет действительным, поэтому разрешение на обращение к другим членам (эффективно this) будет проблематичным.

Обратите внимание, что это согласуется с тем, как работают поля static. В обоих случаях вам разрешен доступ к статическим данным, но не к данным экземпляра. Сообщение об ошибке, которое вы получаете ( "Инициализатор поля не может ссылаться на нестатическое поле, метод или свойство" ), прямо отмечает это.

Ответ 2

"Использовать статический модификатор для объявления статического члена, который принадлежит самому типу, а не конкретному объекту". - статический MSDN

Когда A и B объявляются статическими, они принадлежат типу MyClass, и все экземпляры MyClass будут иметь одинаковое значение для A и B. Статический конструктор будет запущен до того, как будет создан экземпляр класса, но после запуска программы. В этой точке A уже определен, и, таким образом, B может ссылаться на него.

С другой стороны, когда A и B не являются статическими, они принадлежат только экземпляру MyClass. При компиляции поле B будет пытаться инициализироваться на основе значения из A, которое еще не было инициализировано. Нет экземпляра MyClass во время работы компилятора, поэтому для ссылки нет значения A.