7

The SetFields method in the fieldInfo class takes objects as the first parameter. Is there a way to change the value of the static readonly fields using reflection in C#?

So far I have

var field = typeof(ClassName).GetField("FieldName",BindingFlags.Instance|BindingFlags.NonPublic);
vcsjones
  • 138,677
  • 31
  • 291
  • 286
unj2
  • 52,135
  • 87
  • 247
  • 375
  • 3
    Why would you want to do that? If it's your code, don't declare it as static readonly. If it isn't, you'll probably break something. – Richard Jan 05 '12 at 18:16
  • 2
    @Richard While that true there *are* cases when you want to be able to mess around with things "incorrectly". Furthermore, what kind of hacker would kunj2aan be if he *didn't* try to work around the system? – Chris Pfohl Jan 05 '12 at 18:19
  • Similar answer for instance [Can I change a private readonly field in C# using reflection?](http://stackoverflow.com/q/934930) – Michael Freidgeim Aug 23 '16 at 02:50

2 Answers2

10

If you want to get a static field then you should be using BindingFlags.Static instead of BindingFlags.Instance, as the latter is for instance fields.

You can then use field.SetValue(null, newValue) to set the value. Note that null may be passed as the target parameter, because no object instance is needed. Assuming you have sufficient privileges, reflection will happily change the value of a readonly field.

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
  • 1
    I've got funny situation with this, `field.GetValue(null)` returns new value but direct access to field (such as `Trace.WriteLine(FieldName)`) returns old value. – Emperor Orionii Sep 11 '13 at 12:17
  • 1
    Greg, Have you tried this? Because, I'm getting a different result. I can set a readonly instance field this way, but not a readonly static field. – smartcaveman Nov 13 '13 at 19:50
  • 1
    It presumably worked on whatever version of the runtime I tried it on two years ago. But it should be obvious that you're not supposed to do this, that it's breaching your contract with the runtime, and that any updates to the runtime might stop it working. I guess they have! – Greg Beech Nov 13 '13 at 23:00
  • I had this issue while debugging. The debugger showed the updated value but the program continued using the old value. Maybe this has to do with JIT. – AlexDev Jul 04 '14 at 14:14
  • 2
    @AlexDev: The JIT will try to optimize readonly values that it can encode directly into the assembly language (`char`, `int`, etc.), so the value of the field at the time your method first gets invoked will stick for the rest of the application's life cycle. [See this](http://stackoverflow.com/q/38859596/120955) – StriplingWarrior Aug 09 '16 at 21:23
4

You're close. Your BindingFlag is incorrect. Instance means instance field Instead, you should use BindingFlags.Static:

var field = typeof(ClassName).GetField("FieldName",BindingFlags.Static|BindingFlags.NonPublic);
vcsjones
  • 138,677
  • 31
  • 291
  • 286