15

以下不编译。

public class A
{
    private readonly int i;

    public A()
    {
        void SetI()
        {
            i = 10; 
        }

        SetI();
    }
}

它失败并出现此错误:

CS0191 无法分配只读字段(在构造函数或变量初始化程序中除外)

从技术上讲,我们还没有在构造函数中,因为本地函数的可见性是有限的,所以我想知道为什么它不能编译。

4

1 回答 1

23

编译器将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()

不幸的是,C# 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。)

...同样无法编译。

于 2019-03-15T11:35:46.820 回答