Understanding .NET Primitive Types
Sometimes symbols like “int” and “Int32” can be confusing for developers beginning to use C# / .NET.
int vs. System.Int32
Several years ago, I started to learn C# programming. Like many other people, I read some FCL source code from Reflector in C#. The code of System.Int32 looks confusing:
public struct Int32 { internal int m_value; // Other members. }
Because MSDN said that in C#, int is just an alias of System.Int32, the above code should be equal to:
public struct Int32 { internal Int32 m_value; // Other members. }
The confusion is, the fore mentioned code cannot be compiled. As we know, when defining an instance field of a class, the type of the field can be the class itself:
class Class { Class _instanceField; }
However for a struct:
struct Struct { Struct _instanceField; }
The above code cannot be compiled and causes this error message: “Struct member 'Struct._instanceField' of type 'Struct' causes a cycle in the struct layout”. It looks obvious that the above System.Int32 code should not be compiled.
Actually, if switching to IL code insteading of C#, or just checking the code with IL Disassembler, we can see another stuff: int32.
.class public sequential ansi serializable sealed beforefieldinit Int32 extends System.ValueType implements System.IComparable, System.IFormattable, System.IConvertible, System.IComparable`1, System.IEquatable`1 { .field assembly int32 m_value // Other members. }
So what is the relationship among int32 (IL), int (C#) and System.Int32 (C#)?
How does the integer work
int32 is a CLR primitive. Then in FCL, it is represented by System.Int32 struct. The integer value of System.Int32 is persisted on its m_value filed, and a lot of integer-related methods are defined on System.Int32.
In C#, int is just an alias for System.Int32, supported by the C# compiler. So there is no dependency between int and System.Int32, they are not like chicken and egg. These following code are exactly the same:
int integer = new int(); System.Int32 integer = new System.Int32();
So in the first and second code snippet of this post, the actual type of m_value field is not System.Int32 or int, but the int32 CLR primitive type. “int” appears there because Reflector tries to use a C# symbol to represent the CLR symbol. So only the third code snippet of System.Int32 is telling the truth.
In C#, there are two kinds of scenarios to use integer:
- When it is presenting a value, like a local variable, it is compiled into CLR int32 primitive;
- When invoking integer-related method (like int.Parse(), int.ToString(), etc.) on it, it is compiled into the FCL System.Int32 struct (Int32.Parse(), Int32.ToString() are invoked).
Primitive type
Now the concept of primitive type should be clearer. In C#, there are byte (alias of System.Byte, its value is represented by uint8 in CLR), short (System.Int16), int (System.Int32), long (System.Int64), char, float, double, bool, decimal, object, string…. they are specially treated and because they are so frequently used.
For example, one special scenario is, in C#, when defining an enum, only primitive is allowed:
public enum Status : int { }
The corresponding FCL type cannot be used:
public enum Status : Int32 { }
More confusions from primitive type and FCL type
Actually, all we need to know is that the primitive keyword and FCL type name are representing the same thing.
Sometimes, I ask questions about primitive types during the interview. One typical question is, in C# what is the difference between int and System.Int32? The expected answer is just “The same”. But a lot of people, including some senior guys, told me that:
- System.Int32 is 32 bit, while int is 64 bit;
- int is 32 bit integer on 32 bit platform, while it is 64 bit on 64 bit platform;
- int is value type, while System.Int32 is reference type;
- int is allocated in the stack, while System.Int32 is allocated in the heap;
etc.
Another similar question is, what is the difference between string and String in C#? There are answers like:
- string is value type, while String is reference type;
- string is immutable, while String is mutable;
etc.
Maybe some people think these knowledge are not important, I insist understanding basic concepts of programming language should be the first step of professional coding.