c# - .NET 4.x 有重大更改 : Release mode does NOT execute static initializers properly if first call is to default ctor during deserialization

标签 c# .net xml-serialization deserialization static-initialization

首先,我确实理解静态初始化器可以以不同的顺序调用......唯一的保证是它们将在第一次使用该类的任何成员之前执行。

我想说的是,在 .NET 4.x 的 Release模式下,这一保证被违反了。

在为类 X 自动生成反序列化代码期间,它调用类 X 的默认构造函数,并且在该代码中它正在访问尚未初始化的静态成员!

.NET 3.5 从未发生过这种情况;并且它在 .NET 4.x 的 Debug模式下永远不会发生(至少现在还没有)。但在 .NET 4.x 的 Release模式下,这种情况的发生相当一致。

问题:

(1) 是否有一个编译器标志或设置可以关闭 .NET 4.x 添加的优化,以更延迟地评估静态初始值设定项?

(2) 有没有一种方法可以设置 Debug模式来执行所有优化(静态初始化程序除外)?

(3) 我们是否可以在类中放入一些 #pragma 或指令,以使其初始化程序运行得不那么懒惰?

(4) 我看到有人提到静态构造函数可能会影响静态初始值设定项的惰性求值,但不清楚它们是否过度依赖静态初始值设定项顺序。有谁知道使用静态初始化器遍历每个类并添加静态承包商是否可以解决这个问题?

(5) 关于如何解决此问题还有其他建议吗? (回到 .NET 3.5 是非常不可取的,因为我们需要迁移到 64b,并且我们不想失去“编辑并继续”。)

最佳答案

感谢您的上述评论,@dbc;在点击这些链接后,我终于意识到了关键问题:

我对上述保证的陈述是错误的...静态初始化器不保证在第一次使用该类的任何成员之前执行...相反,它们保证在第一次使用之前执行类的任何 STATIC 成员。因此,当反序列化代码调用构造函数来实例化类的实例时,不能保证触发静态初始值设定项。

静态构造函数的规则是不同的......它保证在第一次使用任何构造函数(该类的任何对象的第一次实例化)之前执行。由于它是静态的,因此它将触发所有静态初始化程序运行。

所以,这确实是解决方案:向每个具有静态初始化程序的类添加一个静态构造函数,这些静态初始化程序需要在使用该类之前运行。 (我之前读过关于使用静态构造函数的建议,但他们从未明确指出静态初始化器只能通过访问 STATIC 成员来触发,这与静态构造函数不同。)

(基于 10 多年的 .NET 编码,我非常确定 2.0 到 3.5 的实现是通过实例化类的实例来触发静态初始化器。因此,我仍然断言这是一个重大更改;但语言规范并不认为,过去 10 年我的代码都有错误,而且很幸运它能工作。)

关于c# - .NET 4.x 有重大更改 : Release mode does NOT execute static initializers properly if first call is to default ctor during deserialization,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34972838/

相关文章:

c# 列表查找重复更新多个列表

c# - XAML 如何实例化对象?

c# - (有时)词典中不存在给定的键

c# - 从通用或本地 DateTime 添加/减去的最佳实践

java - 如何通过流读取文件并同时流写入输出来更新 XML 文档

c# - 将带逗号的字符串转换为 double

.net - 了解 32 位与 64 位之间的 CLR 对象大小

c# - 获取当前运行的任务

c# - 在为 ASP.NET Web 服务生成的 WSDL 中的类型定义中控制 "minOccurs"、 "maxOccurs"和 "use"属性?

c# - 将 IEnumerable<T> 对象序列化为字符串数组的扩展方法?