我可以使用reflection更改C#中的私有只读字段吗?

我想知道,因为很多事情可以使用reflection来完成,我可以在构造函数完成执行后更改私有只读字段吗?
(注意:只是好奇)

public class Foo { private readonly int bar; public Foo(int num) { bar = num; } public int GetBar() { return bar; } } Foo foo = new Foo(123); Console.WriteLine(foo.GetBar()); // display 123 // reflection code here... Console.WriteLine(foo.GetBar()); // display 456 

您可以:

 typeof(Foo) .GetField("bar",BindingFlags.Instance|BindingFlags.NonPublic) .SetValue(foo,567); 

显而易见的是尝试一下:

 using System; using System.Reflection; public class Test { private readonly string foo = "Foo"; public static void Main() { Test test = new Test(); FieldInfo field = typeof(Test).GetField ("foo", BindingFlags.Instance | BindingFlags.NonPublic); field.SetValue(test, "Hello"); Console.WriteLine(test.foo); } } 

这工作正常。 (Java有不同的规则,有趣的是你必须明确地设置Field是可访问的,而且它只能用于实例字段。

我同意其他的答案,因为它的工作原理一般 ,特别是E. Lippert的评论,这不是logging的行为,因此也没有面向未来的代码。

但是,我们也注意到另一个问题。 如果您在具有有限权限的环境中运行代码,则可能会遇到exception。

我们刚刚遇到了一些情况,我们的代码在我们的机器上运行良好,但是当代码在受限制的环境中运行时,我们收到了一个VerificationException 。 罪魁祸首是反映了一个只读领域的二传手。 当我们删除该字段的只读限制时,它就起作用了。

你问你为什么要打破这样的封装。

我使用实体帮助类来保湿实体。 这使用reflection来获取新的空实体的所有属性,并将属性/字段名称与结果集中的列匹配,并使用propertyinfo.setvalue()对其进行设置。

我不希望其他人能够改变价值,但我不想花费所有的努力为每个实体定制代码水合方法。

我的许多存储过程返回的结果集不直接对应于表或视图,所以ORM代码对我没有任何帮助。

答案是肯定的,但更重要的是:

你为什么要? 故意打破封装似乎是一个可怕的坏主意给我。

使用reflection来改变只读或常量字段,就像将意想不到的后果 法则与墨菲定律相结合。

不要这样做。

我花了一天的时间修复了一个超现实的bug,其中对象可能不是自己的声明types。

修改只读域一次。 但是,如果你试图再次修改它,你会得到这样的情况:

 SoundDef mySound = Reflection_Modified_Readonly_SoundDef_Field; if( !(mySound is SoundDef) ) Log("Welcome to impossible-land!"); //This would run 

所以不要这样做。

这是在单声道运行时(统一游戏引擎)。

我只是想补充一点,如果你需要做这个unit testing的东西,那么你可以使用:

A) PrivateObject类

B)您仍然需要一个PrivateObject实例,但可以使用Visual Studio生成“Accessor”对象。 如何:重新生成专用访问器

如果你在unit testing之外的代码中设置了一个对象的私有字段,这将是一个“代码异味”的实例我认为,也许唯一的其他原因,你想这样做是如果你正在处理与第三方库,你不能改变目标类的代码。 即使这样,你也许想联系第三方,解释你的情况,看看他们是否不会继续,并改变他们的代码,以适应你的需要。