Ответ 1
Компилятор превращает локальную функцию SetI
в отдельный метод уровня класса. Поскольку этот отдельный метод уровня класса не является конструктором, вы не можете назначать ему поля только для чтения.
Таким образом, компилятор принимает это:
public class A
{
private readonly int i;
public A()
{
void SetI()
{
i = 10;
}
SetI();
}
}
и превращает это в это:
public class A
{
private readonly int i;
public A()
{
<.ctor>g__SetI|1_0();
}
[CompilerGenerated]
private void <.ctor>g__SetI|1_0()
{
i = 10;
}
}
(SharpLab. Я остановил readonly
чтобы он скомпилировался.)
Как видите, он пытается присвоить i
из метода <.ctor>g__SetI|1_0()
, который не является конструктором.
К сожалению, спецификация языка С# 7.0 еще не опубликована, поэтому я не могу ее процитировать.
Точно так же происходит, если вы попытаетесь использовать делегата:
public class A
{
private readonly int i;
public A()
{
Action setI = () => i = 10;
setI();
}
}
Компилируется в:
public class A
{
private readonly int i;
public A()
{
Action action = <.ctor>b__1_0;
action();
}
[CompilerGenerated]
private void <.ctor>b__1_0()
{
i = 10;
}
}
(SharpLab, снова без readonly
.)
... который также не компилируется.