在.Net中为什么String.Empty只读而不是常量?我只是想知道是否有人知道该决定背后的原因是什么.
我偶然发现了这段代码:
static void Main()
{
    typeof(string).GetField("Empty").SetValue(null, "evil");//from DailyWTF
    Console.WriteLine(String.Empty);//check
    //how does it behave?
    if ("evil" == String.Empty) Console.WriteLine("equal"); 
    //output: 
    //evil 
    //equal
 }
我想知道如何编译这段代码甚至是可能的.我的理由是:
根据MSDN String.Empty是只读的,因此更改它应该是不可能的,并且编译应以"无法分配静态只读字段"或类似错误结束.
我认为Base Class Library程序集以某种方式受到保护和签名,以及什么可以防止这种攻击.下次有人可能会更改System.Security.Cryptography或其他关键类.
我认为基类库程序集是在安装.NET之后由NGEN编译的,因此更改String类的字段应该需要高级黑客并且要困难得多.
然而,这段代码编译和工作.有人可以解释我的推理有什么问题吗?
精简版:
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(aka.literal),请参阅" 为什么String.Empty不是常量? ".这意味着,例如,在C#中我们不能string.Empty在以下情况下使用:
switch表格中的陈述case string.Empty:void M(string x = string.Empty) { }[SomeAttribute(string.Empty)]这对于众所周知的"宗教战争"是否影响是否使用string.Empty或"",请参阅" 在C#中,我应该使用string.Empty或String.Empty还是"来初始化字符串? ".
几年前,我Empty通过反射设置其他字符串实例来自娱自乐,看看BCL有多少部分由于它而开始表现奇怪.这是很多.并且Empty参考的变化似乎在应用程序的整个生命周期中持续存在.现在,有一天我试图重复那个小噱头,但后来使用的是.NET 4.5机器,我再也无法做到了.
(注意!如果您的计算机上安装了.NET 4.5,可能PowerShell仍然使用较旧版本的.NET,请尝试复制粘贴[String].GetField("Empty").SetValue($null, "Hello world!")到PowerShell中以查看更改此引用的一些效果.)
当我试图寻找原因时,我偶然发现了一个有趣的主题:" .NET 4.5 beta版本中FatalExecutionEngineError的原因是什么? ".在该问题的公认答案中,是否注意到通过版本4.0,System.String有一个静态构造函数.cctor,其中Empty设置了字段(在C#源中,当然可能只是一个字段初始化程序),而在4.5中没有静态构造函数存在.在这两个版本中,字段本身看起来都是一样的:
.field public …