微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 无法使用反射更改只读字段

所以,我在摆弄和学习反思时遇到了一个奇怪的问题.
我正在尝试更改私有的readonly字段,如下所示:
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方法中第二次读取属性时,属性调用被优化掉(后备字段应该只读,值应该相同)并且旧值被重用.这至少是我的“理论”.

解决方法

JIT正在勾勒出吸气剂:

使用getter上的MethodImplAttribute建议JIT不要内联属性.这不会阻止x的值被内联,但删除readonly将产生所需的结果.

public class A
{
    private static int x;

    public int X
    {
        [MethodImpl(MethodImplOptions.NoInlining)]
        get { return x; }
    }
}

现在输出将是:

0
100

见:Does C# inline properties?

一个简单的解决方法是使用可以为null的整数(int?)值类型.

public class A 
{
    private static readonly int? x;

    public int X
    {
        get
        {
            return x ?? 0;
        }
    }
}

x将不会被内联,因为CLR需要检查x的值是否是对int的有效转换.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐