我有以下代码:
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#中使用反射更改私有只读字段吗?),但是将变量设置为private readonly
可能有一个很好的理由。
你只能使用反射
typeof(MyClass)
.GetField("name",BindingFlags.Instance|BindingFlags.NonPublic)
.SetValue(myclassInstance, 123);
我希望不是。反射可能让你这样做——我不能马上记住它是否服从合理性。
但是你真的不应该尝试这样做…如果某些东西是只读的,那么代码的其他部分很可能依赖于它不改变。
您可以使用反射来做到这一点。我可以贴一个例子,但是这里已经有一个很好的例子了:
http://dotnetproject.blogspot.com/2008/03/systemreflection-how-to-access-and.html但我真的会花很长时间,仔细看看你认为你需要这样做的逻辑。关于类是如何设计的,你是在"违背常规",一旦你开始修改私有字段,可能会出现许多意想不到的行为。开发人员/架构师将它们设置为只读是有原因的,并且可能依赖于它们在实例化后是不可变的。
"仅仅因为我们能做一件事,并不意味着我们应该做一件事。"——Roddenberry
在当前的。net实现中,你可以使用私有反射来修改它。您首先需要获得FieldInfo
与BindingFlags.NonPublic|BindingFlags.Instance
,并使用它来改变值。
但我认为另一个/未来的实现是允许实际执行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;}}
根据MSDN规范,您只能使用反射来检索公共字段/成员,因此该路径不应该是可能的。不过,您可以指定自己的绑定标志来解决这个问题。我还没试过呢。
我不确定它在c#中是否可行,但你可以去非托管,并尝试直接操作内存。但是我猜测这将以异常告终,因为Windows很可能不允许这样做。