C# readonly vs Java final

Posted

技术标签:

【中文标题】C# readonly vs Java final【英文标题】: 【发布时间】:2013-02-08 05:35:20 【问题描述】:

在 Java 中,final 表示一个变量只能分配一次,但该分配可以在程序中的任何位置进行。在 C# 中,readonly 意味着一个字段只能在 constructor 中分配,这在 IMO 中是非常有用的。

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

编辑:

响应 cmets;我想指出,我很清楚不变性的好处,而且我到处都在使用它。我相信readonly 没有Java那么有用,因为:

public class Foo 

    private readonly int _bar;

    Foo()
    
        _bar = 5;
    

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

public class Foo 

    private readonly int _bar;

    Foo()
    
        initialize()
    

    private void initialize()
    
        _bar = 5; //Can't compile because of semantics of readonly
         

【问题讨论】:

你的“不那么有用”是我的“更安全”。 不变性有什么好处?我想你会发现readonly 对编译器非常有用。你的问题本质上是主观的。 您也不能在 java 程序中的任何地方为最终变量赋值。如果您正在制作一个静态最终常量,那么您需要在现场给出值,否则如果您将变量作为最终值,那么您可以在构造函数中启动它。 @JohnSaunders 这不是重复的。他不是在问Java 在 C# 中的 final 的等价物。他表明他已经知道这一点。我认为您没有费心阅读这个问题,因为它完全不同。 这个问题基于一个错误的前提,您可以在类中的任何位置初始化最终的Java 字段。你不能做这个!第二个示例也不会在 Java 中编译(使用 final)。 【参考方案1】:

这是一个老问题,但我认为值得注意的是,这在 Java 15 中工作:

public class Main

   final int testInt;

   public Main()
   
      init();
   

   private void init() 
   
      testInt = 3;
   

java: 变量 testInt 未在默认构造函数中初始化

所以看起来 C# readonly 和 Java final 的行为方式相同。

【讨论】:

【参考方案2】:

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

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

在我看来,这并没有降低 readonly 关键字的价值。我将它用于仅由构造函数提供值的字段(例如,创建列表或存储构造函数参数)。 C# 将确保我不会再更改该字段,确保我不会意外地将其设置为 null 或任何东西。

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

【讨论】:

@Virtlink 谢谢你的回答。很高兴不是每个人都只是寻找借口来结束事情。 第一段错误。您可以通过反射修改只读字段,仅使用安全的 C# 和可验证的 IL。您甚至可以通过这种方式更改string.Empty 的值。也许您的意思是可信代码,它与verifiable IL 是完全不同的概念。不受信任的代码不能使用(大部分)反射,但可验证的 IL 可以。 @Timwi 你是对的,但是当你把反思带入画面时,所有的赌注都没有了。我没有提到它,因为它与问题无关。这让我的第一段没有,最多不完整 奇怪的是 Java final 和 C# 只读,为了这个问题,它们的工作方式完全相同:你不能在类中的任何地方为它们赋值,只能在构造函数中或它的声明 @Virtlink 你用的是什么java编译器?查看问题的第二个在 Java 中不起作用的示例:ideone.com/iq1EbV。

以上是关于C# readonly vs Java final的主要内容,如果未能解决你的问题,请参考以下文章

与 C# 相比,Java 的 final 类似于 const 或 readonly [重复]

Java入门系列之final

Java有没有readonly

Java——私有构造函数 vs final 等等

csharp Const Vs readonly

用VS2010编C#程序扫盲 2