Unable to change readonly field with reflection

So, I ran into some strange problem, messing around and thinking. I am trying to change the private readonly field as shown below:

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(); } 

If I run the program in the form in which it stands above, then 0 will be printed to the console every time. However, if I comment on the first fingerprint, the second will write out the expected 100.

Who can shed light on what is happening here? Thanks!

EDIT: Oddly enough, this works in Visual Studio 2012, but not in 2010. As I understand it, the settings are the same for both.

EDIT 2: Works when building with the x64 target platform, not x86. Guess the new question: why is this?

EDIT 3: Compared to x64 and x86 versions when disassembling; x86 version has some kind of insert.

EDIT 4: Okey, I think I understood what was going on, sort of. I do not think that the property in class A is built-in - the problem. I believe that when it's time to read the property a second time in the main method, the call to the property is optimized (the support field should be read-only, the value should be the same), and the old value is reused. This is my "theory" at least.

+7
reflection c # readonly
source share
1 answer

JIT inserts a getter:

Use the MethodImplAttribute on the getter to suggest the JIT not embed the property. This will not prevent you from entering the x value, but deleting readonly will produce the desired result.

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

Now the output will be:

 0 100 

See: Are there any built-in C # properties?

One simple solution is to use a value type with a zero number ( int? ).

 public class A { private static readonly int? x; public int X { get { return x ?? 0; } } } 

x will not be inserted, as the CLR will need to check if the value of x valid cast to int .

+6
source share

All Articles