C# readonly 与 Java final

标签 c# .net clr language-design readonly

在 Java 中,final 表示一个变量只能被赋值一次,但该赋值可以发生在程序的任何地方。在 C# 中,readonly 表示只能在构造函数 中分配一个字段,在我看来,这明显没那么有用。

众所周知,C# 深受 Java 设计的影响,但这种差异一直让我感到困惑,因为它很奇怪。有谁知道 CLR 中是否存在技术原因,导致 C# 的 readonly 与 Java 的 final 相比没有那么有用的行为?

编辑:

回应评论;我想指出的是,我很清楚不变性的好处,而且我到处都在使用它。我认为 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 的行为有一个技术原因:在创建的程序集的元数据中,该字段标有 initonly 属性,该属性将确保该字段未在构造函数外修改。1 然而,虽然无法验证,但通过获取只读字段的地址,仍然可以更改其值。可验证的 IL 和 C# 不允许您这样做。

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

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

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

关于C# readonly 与 Java final,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15026924/

相关文章:

c# - 使用泛型在类的值类型之间进行转换

c# - 批量搜索文档 Elasticsearch

c# - 按总金额分组项目

c# - 在互操作(C++ 管理)项目中使用 C# dll(使用 Microsoft.bcl 构建)

c# - 使用 LINQ 将 List<U> 转换为 List<T>

c# - 当我的应用程序失败时如何通知 Windows 任务计划程序?

.net - 上次调试 session 的应用程序见解

.net - 如何获取 Azure 通知中心注册设备列表

c# - 当我们将线程的引用更改为 null 时会发生什么?

c# - 使用 Process.Start 运行 C++ exe 与使用 CLR 包装 C++ 代码