Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Int32 contains... another System.Int32

I used reflection to inspect the contents of System.Int32 and found that it contains another System.Int32.

System.Int32 m_value;

I don't see how that's possible.

This int really is the "backing integer" of the one you have: if you box an int and use reflection to change the value of its m_value field, you effectively change the value of the integer:

object testInt = 4;
Console.WriteLine(testInt); // yields 4

typeof(System.Int32)
    .GetField("m_value", BindingFlags.NonPublic | BindingFlags.Instance)
    .SetValue(testInt, 5);
Console.WriteLine(testInt); // yields 5

There's gotta be a rational explanation behind this singularity. How can a value type contain itself? What magic does the CLR use to make it work?

like image 304
zneak Avatar asked Jul 30 '10 20:07

zneak


People also ask

What is System Int32?

Int32 is an immutable value type that represents signed integers with values that range from negative 2,147,483,648 (which is represented by the Int32. MinValue constant) through positive 2,147,483,647 (which is represented by the Int32. MaxValue constant. .

What does Int32 mean C#?

In C#, Int32 Struct represents 32-bit signed integer(also termed as int data type) starting from range -2,147,483,648 to +2,147,483,647. It also provides different types of method to perform various operations. You can perform the mathematical operation like addition, subtraction, multiplication, etc. on Int32 type.

How many digits are in an Int32?

Int32 Structure. This type is safe for multithreaded operations. The Int32 value type represents signed integers with values ranging from negative 2,147,483,648 through positive 2,147,483,647.

What is the difference between int and Int32 in C#?

What is the difference between int and Int32 in C#? Int32 is a type provided by . NET framework whereas int is an alias for Int32 in C# language.


2 Answers

As noted, a 32-bit integer can exist in two varieties. Four bytes anywhere in memory or a CPU register (not just the stack), the fast version. And it can be embedded in System.Object, the boxed version. The declaration for System.Int32 is compatible with the latter. When boxed, it has the typical object header, followed by 4 bytes that stores the value. And those 4 bytes map exactly to the m_value member. Maybe you see why there's no conflict here: m_value is always the fast, non-boxed version. Because there is no such thing as a boxed boxed integer.

Both the language compiler and the JIT compiler are keenly aware of the properties of an Int32. The compiler is responsible for deciding when the integer needs to be boxed and unboxed, it generates the corresponding IL instructions to do so. And it knows what IL instructions are available that allows the integer to be operated on without boxing it first. Readily evident from the methods implemented by System.Int32, it doesn't have an override for operator==() for example. That's done by the CEQ opcode. But it does have an override for Equals(), required to override the Object.Equals() method when the integer is boxed. Your compiler needs to have that same kind of awareness.

like image 62
Hans Passant Avatar answered Sep 22 '22 06:09

Hans Passant


Check out this thread for a laborious discussion of this mystery.

like image 26
Jason Avatar answered Sep 25 '22 06:09

Jason