Почему С# не разрешает инициализатор поля с нестатическими полями?
Почему С# разрешит это:
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 не нашел дубликата.
Ответы
Ответ 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
.