Been browsing through .NET source code of .NET Framework Reference Source, just for fun of it. And found something I don't understand.
There is a Int32.cs file with C# code for Int32
type. And somehow that seems strange to me. How does the C# compiler compile code for Int32
type?
public struct Int32: IComparable, IFormattable, IConvertible { internal int m_value; // ... }
But isn't this illegal in C#? If int
is only an alias for Int32
, it should fail to compile with Error CS0523:
Struct member 'struct2 field' of type 'struct1' causes a cycle in the struct layout.
Is there some magic in the compiler, or am I completely off track?
isn't this illegal in C#? If "int" is only alias for "Int32" it should fail to compile with error CS0523. Is there some magic in the compiler?
Yes; the error is deliberately suppressed in the compiler. The cycle checker is skipped entirely if the type in question is a built-in type.
Normally this sort of thing is illegal:
struct S { S s; int i; }
In that case the size of S is undefined because whatever the size of S is, it must be equal to itself plus the size of an int. There is no such size.
struct S { S s; }
In that case we have no information from which to deduce the size of S.
struct Int32 { Int32 i; }
But in this case the compiler knows ahead of time that System.Int32
is four bytes because it is a very special type.
Incidentally, the details of how the C# compiler (and, for that matter, the CLR) determines when a set of struct types is cyclic is extremely interesting. I'll try to write a blog article about that at some point.
int
is an alias for Int32
, but the Int32
struct you are looking at is simply metadata, it is not a real object. The int m_value
declaration is possibly there only to give the struct the appropriate size, because it is never actually referenced anywhere else (which is why it is allowed to be there).
So, in other words, the compiler kind of saves this from being a problem. There is a discussion on the topic in the MSDN Forums.
From the discussion, here is a quote from the chosen answer that helps to try to determine how the declaration is possible:
while it is true that the type contains an integer m_value field - the field is never referenced. In every supporting method (CompareTo, ToString, etc), "this" is used instead. It is possible that the m_value fields only exist to force the structures to have the appropriate size.
I suspect that when the compiler sees "int", it translates it into "a reference to System.Int32 in mscorlib.dll, to be resolved later", and since it's building mscorlib.dll, it does end up with a cyclical reference (but not one that can ever cause problems, because m_value is never used). If this assumption is correct, then this trick would only work for special compiler types.
Reading further, it can be determined that the struct is simply metadata, and not a real object, so it is not bound by the same recursive definiton restraints.
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