设置只读字段(这是个错误吗?)
设置只读字段(这是个错误吗?)
只是在使用C#玩耍时,意识到了一件奇怪的事情。\n以下是代码:\n
class Program { static void Main(string[] args) { System.Diagnostics.Debug.Write(string.Empty); typeof(string) .GetField("Empty", BindingFlags.Static | BindingFlags.Public) .SetValue(null, "Tolgahan"); Console.WriteLine(string.Empty); // 输出:Tolgahan } }
\n为什么反射允许我们修改只读字段?\n
\n问题是“为什么允许通过反射进行设置”,而不是“如何做到”,因此它不是Can I change a private readonly field in C# using reflection?的重复。
readonly字段的设置(这是一个bug吗?)是因为readonly关键字只是防止Murphy,而不是Machiavelli*。
我们使用readonly、private和其他限制我们所能做的任何东西,主要是因为我们希望限制更多的错误、不一致或纯粹愚蠢的事情,而不是有用和有益的事情。
但它仍然只是二进制的表示。如果某个内存被设置为数字"42",并且我们通过一个readonly字段访问它,那么在对象创建时它是不是readonly的。除了编译器发现"嘿,首先你说你不想改变它,现在你正在试图改变它,怎么回事?这两个决定中肯定有一个是错误的"之外,没有任何阻止它被改变的东西。
现在,没有承诺反射能够改变它,但也没有承诺它不能。目前,反射的工作方式和readonly的工作方式意味着你可以改变它。至少,这将需要很多工作(可能会对我们用户和需要实施这项工作的团队产生影响)才能阻止那些认为自己有充分理由的人去这样做。
请注意,与反射相关的权限确实阻止了Machiavelli的行为,
*Murphy严格来说是在谈论我们应该如何设计事物来防止人们意外做出灾难性的事情-readonly是一个很好的例子,不能以错误的方式插入的插头是更好的-而Machiavelli是在教学而不是实践技巧。尽管这样说不那么简洁。
.s.w.g是Murphy和Machiavelli的什么意思?我不能够声称这是我的功劳。我所知道的最早的类似用法(关于C++中的private)是由Bjarne Stroustrup提出的,尽管我不知道他是否是第一个。