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?
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. .
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.
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#? Int32 is a type provided by . NET framework whereas int is an alias for Int32 in C# language.
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.
Check out this thread for a laborious discussion of this mystery.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With