C#readonly vs Java final

MgS*_*Sam 10 .net c# clr language-design readonly

在Java中,final意味着变量只能分配一次,但该分配可以在程序中的任何位置进行.在C#中,readonly意味着只能在构造函数中分配一个字段,IMO对它的用处非常少.

众所周知,C#受Java设计的影响很大,但这种差异一直让我感到非常奇怪.有没有人知道CLR中是否存在技术原因导致C#readonly与Java的行为不太有用final

编辑:

回应评论; 我想指出,我很清楚不变性的好处,而且我在整个地方都使用它.我相信readonly没有Java那么有用,因为:

public class Foo 
{
    private readonly int _bar;

    Foo()
    {
        _bar = 5;
    }
}
Run Code Online (Sandbox Code Playgroud)

哎呀,我实际上需要在辅助方法中初始化该值!

public class Foo 
{
    private readonly int _bar;

    Foo()
    {
        initialize()
    }

    private void initialize()
    {
        _bar = 5; //Can't compile because of semantics of readonly
    }     
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*ker 15

这里一个技术原因的行为readonly:在创建集的元数据字段标有initonly这将确保该字段不修改的构造函数外属性.1然而,虽然无法验证,但通过获取只读字段的地址,仍然可以更改其值.可验证的IL和C#不允许您这样做.

在编译时,不可能对所有方法强制执行此操作,因为编译器必须分析可以调用方法的所有可能的顺序.在运行时,如果必须检查每个字段是否已写入之前,它可能会对CLR造成负担并对性能产生负面影响.相反,更安全的是C#和CLR不允许在除了精心分析的构造函数范围之外的任何地方为字段分配值.

在我看来,这并不会使readonly关键字的价值降低.我在整个地方使用它的值只由构造函数提供的字段(例如创建一个列表,或存储一个构造函数参数).C#将确保我再也不会改变字段,确保我不会意外地将其设置为null或任何东西.

1)感谢Eric Lippert指出这一点.

  • @Timwi你是正确的,但是当你在图片中反射时,所有的赌注都关闭了。我没有提到它,因为它与问题无关。这使我的第一段最多不会_不完整_。 (2认同)