c# - 只读是否有任何运行时开销?

标签 c# performance readonly immutability

出于某种原因,我一直假设 readonly 字段有与之相关的开销,我认为这是 CLR 跟踪是否是 readonly字段是否已经初始化。这里的开销是一些额外的内存使用,以跟踪状态和分配值时的检查。

也许我这么认为是因为我不知道readonly 字段只能在构造函数内或字段声明本身内初始化,如果没有运行时检查,你将无法以保证它不会以各种方法被多次分配。但现在我知道了,它可以很容易地被 C# 编译器静态检查,对吧?那么是这样吗?

另一个原因是我读到过 readonly 的使用对性能有“轻微”的影响,但他们从未讨论过这个声明,我找不到关于这个主题的信息,因此我的问题。除了运行时检查之外,我不知道还有什么其他性能影响。

第三个原因是我看到readonly作为initonly保存在编译后的IL中,那么这个信息在IL中的原因是什么readonly 只不过是 C# 编译器保证该字段永远不会分配给构造函数或声明之外的内容?

另一方面,我发现您可以通过反射设置 readonly int 的值,而 CLR 不会抛出异常,这在 readonly< 时是不可能的 是运行时检查。

所以我的猜测是:'readonlyness' 只是一个编译时特性,任何人都可以确认/否认这一点吗?如果是,将此信息包含在 IL 中的原因是什么?

最佳答案

您必须从与访问修饰符相同的角度来看待它。访问修饰符存在于 IL 中,但它们真的是运行时检查吗? (1) 我不能在编译时直接分配私有(private)字段,(2) 我可以使用反射分配它们。到目前为止,它似乎没有运行时检查,比如readonly

但让我们检查一下访问修饰符。执行以下操作:

  1. 使用公共(public)类 C 创建程序集 A.dll
  2. 创建一个引用 A.dll 的程序集 B.exe。 B.exe 使用类 C。
  3. 构建两个程序集。运行 B.exe 工作正常。
  4. 重建 A.dll 但将类 C 设置为内部。替换B.exe目录下的A.dll。

现在,运行 B.exe 会引发运行时异常。

访问修饰符也存在于 IL 中,对吗?那么他们的目的是什么?目的是引用 .Net 程序集的其他程序集需要知道允许访问什么以及不允许访问什么,包括编译时和运行时。

Readonly 在 IL 中似乎有类似的目的。它告诉其他程序集他们是否可以写入特定类型的字段。但是,readonly 似乎 没有与上面示例中的访问修饰符相同的运行时检查。似乎 readonly 是编译时检查,不会在运行时发生。在此处查看性能示例:Read-only performance vs const .

同样,这并不意味着 IL 没有用。 IL 确保首先发生编译时错误。请记住,当您构建时,您不是针对代码构建的,而是针对程序集构建的。

关于c# - 只读是否有任何运行时开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/913400/

相关文章:

c# - 在三层项目中放置 DTO/POCO

c# - 在 Emgu CV 中何时使用 `image` 以及何时使用 `Matrix`?

windows - 性能随机下降

javascript - 在客户端的浏览器中解压缩内容

c# - WPF GridView 中的可编辑组合框

C# 货币转换器 : Reduce the amount of if statements

c# - 为什么 C# 的 System.Collections 库中没有 ReadOnlyList<T> 类?

redis - Redis中是否有只读连接?

sql - 派生查询抛出错误 ORA-00604 : error occurred at recursive SQL level 1

c# - Entity Framework : 'The SqlParameter is already contained by another SqlParameterCollection'