虽然我明白改变String.Empty
的价值会是一个坏主意,但我不明白为什么我不能这样做。
要理解我的意思,请考虑以下课程:
public class SomeContext
{
static SomeContext(){}
public static readonly string Green = "Green";
public static readonly SomeContext Instance = new SomeContext();
private SomeContext(){}
public readonly string Blue = "Blue";
public static void PrintValues()
{
Console.WriteLine(new { Green, Instance.Blue, String.Empty }.ToString());
}
}
我有一个小的控制台应用程序试图操纵这三个只读字段。它可以成功地将蓝色和绿色变成粉红色,但是Empty保持不变:
SomeContext.PrintValues();
/// prints out : { Green = Green, Blue = Blue, Empty = }
typeof(SomeContext).GetField("Blue").SetValue(SomeContext.Instance, "Pink");
typeof(SomeContext).GetField("Green", BindingFlags.Public | BindingFlags.Static).SetValue(null, "Pink");
typeof(String).GetField("Empty", BindingFlags.Public | BindingFlags.Static).SetValue(null, "Pink");
SomeContext.PrintValues();
/// prints out : { Green = Pink, Blue = Pink, Empty = }
最初,我也问过为什么String.Empty
不是常数。我找到了问题on another post的这一部分的答案,并删除了问题的这一部分。
注意:没有任何“重复”对此问题有明确的答案,这就是我问这个问题的原因。
答案 0 :(得分:16)
您无法更改它,因为您的计算机上安装了.NET 4.5。只需将项目的“框架目标”设置更改为3.5,您就会看到它的工作原理。
CLR具有String.Empty的内置知识。例如,您将看到一个Reflector或Reference Source,System.String类从不初始化它。它是在CLR启动期间完成的。确切地说4.5如何防止修改可见是有点难以辨别的。你实际上做了修改字段,只需添加以下代码行:
var s = typeof(String).GetField("Empty",
BindingFlags.Public | BindingFlags.Static).GetValue(null);
Console.WriteLine(s);
你会看到“粉红色”。我的 guess 是它被抖动截获的。但是我无法给出确凿的证据。有先例,尝试修补Decimal.MaxValue,例如,另一个只读静态值。在3.5中也不可更改,抖动会识别它并直接生成值而无需读取字段。
我刚刚发现你在another question上给了一个完全相同主题的赏金。 280Z28的帖子非常相似。