Почему C# не позволяет инициализировать поля с нестатическими полями?
Почему C# позволит это:
public class MyClass
{
static int A=1;
static int B=A+1;
}
Но не позволит ("Инициализатор поля не может ссылаться на нестатическое поле, метод или свойство") это
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 не нашел дубликатов.
2 ответа
Меня больше интересует причина / логика, почему это было ограничено. просто для любопытства.
Если вы читаете спецификацию языка C#, 10.11.3, это намекает на обоснование здесь. При обсуждении инициализаторов переменных:
Полезно думать об инициализаторах переменных экземпляра и инициализаторах конструктора как о операторах, которые автоматически вставляются перед телом конструктора.
Поскольку они "вставляются перед конструктором", они выполняются до this
быть действительным, поэтому позволяет вам ссылаться на других участников (эффективно this
) было бы проблематично.
Обратите внимание, что это согласуется с тем, как static
поля тоже работают. В обоих случаях вам разрешен доступ к статическим данным, но не к данным экземпляра. Полученное сообщение об ошибке ("Инициализатор поля не может ссылаться на нестатическое поле, метод или свойство") прямо указывает на это.
"Используйте модификатор static, чтобы объявить статический член, который принадлежит самому типу, а не конкретному объекту". - статический MSDN
когда A
а также B
объявлены статическими они относятся к типу MyClass
и все случаи MyClass
будет иметь то же значение для A
а также B
, Статический конструктор будет запущен до создания экземпляра класса, но после запуска программы. В таком случае, A
уже определен, и, таким образом, B
могу сослаться на это.
С другой стороны, когда A
а также B
не являются статичными, они принадлежат только экземпляру MyClass
, При компиляции поле B
будет пытаться инициализироваться на основе значения из A
который еще не был инициализирован. Там нет ни одного случая MyClass
в то время как компилятор работает, и поэтому нет значения A
для ссылки.