【发布时间】:2013-08-06 05:18:07
【问题描述】:
所以,我在摆弄和学习反思时遇到了一个奇怪的问题。 我正在尝试更改一个私有的只读字段,如下所示:
public class A
{
private static readonly int x;
public int X
{
get { return x; }
}
}
static void Main(string[] args)
{
A obj = new A();
Type objType = typeof(A);
Console.WriteLine(obj.X);
FieldInfo objField = objType.GetField("x", BindingFlags.Static | BindingFlags.NonPublic);
objField.SetValue(null, 100);
Console.WriteLine(obj.X);
Console.ReadLine();
}
如果我按照上面的方式运行程序,那么每次都会将 0 打印到控制台。 但是,如果我注释掉第一个打印,那么第二个将写出预期的 100。
谁能解释一下这里发生了什么?谢谢!
编辑:奇怪的是,它似乎在 Visual Studio 2012 中有效,但在 2010 年无效。据我发现,两者的设置相同。
编辑 2:使用平台目标 x64 构建时有效,而不是 x86。猜猜新问题是:为什么会这样?
编辑3:在反汇编中比较了x64和x86版本; x86 版本中似乎有一些内联。
编辑 4:好吧,想想我已经弄清楚发生了什么,有点。我不认为 A 类中的属性被内联是问题。我相信当在 main 方法中第二次读取属性时,属性调用被优化掉(支持字段应该是只读的,值应该相同)并且旧值被重用。至少这是我的“理论”。
【问题讨论】:
-
那是因为您第一次打印时调用它,为其分配默认值,即 0,之后始终为 0,如果您注释掉第一个,那么您将分配值 100 和然后打印它的值。
-
打电话给 Marc Gravel,打电话给 Marc Gravel
-
由于该字段被标记为
readonly,JIT 可能会内联Xgetter。 -
@terrybozzio 是的,看起来合乎逻辑,但根据我在此站点上其他线程中所读到的内容,您应该能够通过使用反射来更改只读字段。除非我误解了什么
-
我无法在我的机器上重现您的问题。也就是说,您提供的代码实际上按预期工作。只是为了证明我没有带你走花园小路:i.imgur.com/ZR1U7vW.png
标签: c# reflection readonly