短版:
C# 代码
typeof(string).GetField("Empty").SetValue(null, "Hello world!");
Console.WriteLine(string.Empty);
编译并运行时,给出输出
"Hello world!"
在 .NET 4.0 及更早版本下,但提供 ""
在 .NET 4.5 和 .NET 4.5.1 下。如何像这样忽略对字段的写入,或者谁重置该字段?
加长版:
我从来没有真正理解为什么
string.Empty
字段(也称为 [mscorlib]System.String::Empty
)不是 const
(又名 literal
),参见“Why isn't String.Empty a constant?”。这意味着,例如,在 C# 中我们不能使用 string.Empty
在以下情况下:switch
声明形式 case string.Empty:
void M(string x = string.Empty) { }
[SomeAttribute(string.Empty)]
这对众所周知的“宗教 war ”是否使用
string.Empty
有影响或 ""
,见“In C#, should I use string.Empty or String.Empty or "" to intitialize a string?”。几年前,我通过设置
Empty
自娱自乐。通过反射到其他一些字符串实例,看看 BCL 的多少部分因此开始表现异常。这是相当多的。和Empty
的变化引用似乎在应用程序的整个生命周期中都存在。现在,前几天我试图重复那个小特技,但后来使用了 .NET 4.5 机器,我再也做不到了。(注意!如果你的机器上有 .NET 4.5,可能你的
PowerShell
仍然使用旧版本的 .NET(编辑:仅适用于 Windows 7 或更旧版本,其中 PowerShell 没有更新到 PowerShell 2.0 以上),所以尝试复制-将 [String].GetField("Empty").SetValue($null, "Hello world!")
粘贴到 PowerShell 中以查看更改此引用的一些效果。)当我试图寻找原因时,我偶然发现了有趣的线程“What's the cause of this FatalExecutionEngineError in .NET 4.5 beta?”。在该问题的公认答案中,是否注意到通过 4.0 版,
System.String
有一个静态构造函数 .cctor
其中领域Empty
已设置(在 C# 源代码中,当然,这可能只是一个字段初始值设定项),而在 4.5 中不存在静态构造函数。在这两个版本中,字段本身看起来是一样的:.field public static initonly string Empty
(如 IL DASM 所见)。
除
String::Empty
外没有其他字段似乎受到了影响。作为一个例子,我试验了 System.Diagnostics.Debugger::DefaultCategory
.这种情况看起来很相似:一个包含 static readonly
的密封类( static initonly
) string
类型的字段.但是在这种情况下,通过反射更改值(引用)可以正常工作。回到问题:
从技术上讲,
Empty
怎么可能?当我设置字段时,似乎没有改变(在 4.5 中)?我已经验证 C# 编译器不会在读取时“作弊”,它输出 IL 如下:ldsfld string [mscorlib]System.String::Empty
所以应该阅读实际的领域。
在对我的问题进行悬赏后编辑:请注意,写操作(肯定需要反射,因为字段是
readonly
(在 IL 中又名 initonly
))实际上按预期工作。它是 阅读 异常的操作。如果你用反射阅读,如 typeof(string).GetField("Empty").GetValue(null)
,一切正常(即看到值的变化)。请参阅下面的评论。所以更好的问题是:为什么这个新版本的框架在读取这个特定字段时会作弊?
最佳答案
不同之处在于新版本 .NET 的 JIT,它显然优化了对 String.Empty
的引用。通过内联对特定 String
的引用实例而不是加载存储在 Empty
中的值 field 。这在 的定义下是合理的。仅初始化约束 在 ECMA-335 Partition I §8.6.1.2 中,可以解释为 String.Empty
的值String
后字段不会改变类被初始化。
关于c# - 更改了 .NET 4.5 中 string.Empty(或 System.String::Empty)的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16618302/