【问题标题】:Modify private readonly member variable?修改私有只读成员变量?
【发布时间】:2011-10-24 13:28:12
【问题描述】:

我有以下代码:

public class MyClass
{
    private readonly string name;
    public string Name
    {
        get
        {
            return name;
        }
    }
    public MyClass(string name)
    {
        this.name = name;
    }
}
class Program
{
    static void Main(string[] args)
    {
        MyClass mc = new MyClass("SomeName");
    }
}

有什么方法可以在不修改类的情况下更改 mc.name 的值?

【问题讨论】:

标签: c# readonly private-members


【解决方案1】:

使用reflection,是的(Can I change a private readonly field in C# using reflection?),但变量设置为private readonly 可能有一个很好的理由。

【讨论】:

  • @AdamFlanagan 这只是出于好奇。我意识到它可能是私有只读的。
【解决方案2】:

你只能使用反射

typeof(MyClass)
   .GetField("name",BindingFlags.Instance|BindingFlags.NonPublic)
   .SetValue(myclassInstance, 123);

【讨论】:

    【解决方案3】:

    我希望不会。反射可能让你这样做 - 我不记得它是否服从只读性。

    但是您真的不应该尝试这样做...如果某些内容是只读的,则代码的其他部分很可能取决于它不会改变。

    【讨论】:

    • 刚刚测试过,目前的实现是允许的。但据我记得,规范允许readonly 永远不会改变的实现。
    • @JonSkeet 显然是这样。但这只是出于好奇。我意识到可能不应该修改这样的东西。
    【解决方案4】:

    您可以使用反射来做到这一点。我可以发布一个示例,但这里已经有一个非常好的示例:

    http://dotnetproject.blogspot.com/2008/03/systemreflection-how-to-access-and.html

    但我真的会仔细研究一下使您达到您认为需要这样做的逻辑的逻辑。关于类的设计方式,您正在“切中要害”,一旦您开始修改私有字段,可能会出现 许多 意想不到的行为。开发人员/架构师将它们设为只读是有原因的,并且可能依赖于它们在实例化后是不可变的。

    “仅仅因为我们可以做一件事,并不意味着我们应该做一件事。” - 罗登莓

    【讨论】:

      【解决方案5】:

      在当前的 .net 实现中,您可以使用私有反射对其进行修改。您首先需要使用BindingFlags.NonPublic|BindingFlags.Instance 获取FieldInfo 并使用它来更改值。

      但我认为允许另一个/未来的实现实际执行readonly。例如,JITter 可能会将值嵌入到已编译的代码中。这意味着您的代码可能会在 .net 的未来版本中中断。所以我建议不要依赖这种行为。


      示例代码:

      void Main()
      {
         this.GetType()
           .GetField("name", BindingFlags.NonPublic | BindingFlags.Instance)
           .SetValue(this, "Yes");
      
         Name.Dump();
      }
      
      private readonly string name="No";
      
      public string Name{get{return name;}}
      

      【讨论】:

        【解决方案6】:

        根据 MSDN 规范,您只能使用反射检索公共字段/成员,因此该路径应该是不可能的。但是您可以指定自己的绑定标志来解决这个问题。不过我没试过。

        我不确定它在 C# 中是否可行,但您可以不受管理,并尝试直接操作内存。但我猜测这最终会出现异常,因为 Windows 很可能不允许这样做。

        【讨论】:

          猜你喜欢
          • 2016-02-07
          • 1970-01-01
          • 2013-02-15
          • 1970-01-01
          • 1970-01-01
          • 2011-04-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多