c# - Si Int32 es solo un alias para int, ¿cómo puede la clase Int32 usar un int?
compiler-construction internals (2)
¿No es esto ilegal en C #? Si "int" es solo un alias para "Int32", no debería compilarse con el error CS0523. ¿Hay algo de magia en el compilador?
Sí; el error se suprime deliberadamente en el compilador. El comprobador de ciclos se omite por completo si el tipo en cuestión es de tipo incorporado.
Normalmente este tipo de cosas es ilegal:
struct S { S s; int i; }
En ese caso, el tamaño de S no está definido porque, sea cual sea el tamaño de S, debe ser igual a él más el tamaño de un int. No hay tal tamaño.
struct S { S s; }
En ese caso, no tenemos información para deducir el tamaño de S.
struct Int32 { Int32 i; }
Pero en este caso el compilador sabe de antemano que System.Int32
tiene cuatro bytes porque es un tipo muy especial.
A propósito, los detalles de cómo el compilador de C # (y, para el caso, el CLR) determina cuándo un conjunto de tipos de estructuras es cíclico es extremadamente interesante. Trataré de escribir un artículo de blog sobre eso en algún momento.
He estado navegando a través del código fuente .NET de .NET Framework Reference Source , solo por diversión. Y encontré algo que no entiendo.
Hay un archivo Int32.cs con código C # para el tipo Int32
. Y de alguna manera eso me parece extraño. ¿Cómo funciona el código de compilación del compilador C # para el tipo Int32
?
public struct Int32: IComparable, IFormattable, IConvertible {
internal int m_value;
// ...
}
¿Pero no es esto ilegal en C #? Si int
es solo un alias para Int32
, no debería compilarse con el error CS0523 :
El miembro de estructura ''struct2 field'' del tipo ''struct1'' causa un ciclo en el diseño de la estructura.
¿Hay algo mágico en el compilador, o estoy completamente fuera de la pista?
int
es un alias para Int32
, pero la estructura Int32
que está viendo es simplemente metadata, no es un objeto real. La declaración int m_value
posiblemente solo esté ahí para dar a la estructura el tamaño apropiado, porque en realidad nunca se hace referencia en otro lugar (por lo que está permitido que esté allí).
Entonces, en otras palabras, el tipo de compilador evita que esto sea un problema. Hay una discusión sobre el tema social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/… .
A partir de la discusión, aquí hay una cita de la respuesta elegida que ayuda a tratar de determinar cómo es posible la declaración:
si bien es cierto que el tipo contiene un campo m_value entero, el campo nunca se referencia. En cada método de soporte (CompareTo, ToString, etc.), se usa "this" en su lugar. Es posible que los campos m_value solo existan para obligar a las estructuras a tener el tamaño apropiado.
Sospecho que cuando el compilador ve "int", lo traduce como "una referencia a System.Int32 en mscorlib.dll, que se resolverá más tarde", y dado que está construyendo mscorlib.dll, termina con una referencia cíclica ( pero no uno que pueda causar problemas, porque m_value nunca se usa). Si esta suposición es correcta, entonces este truco solo funcionaría para tipos de compiladores especiales.
Leyendo más, se puede determinar que la estructura es simplemente metadata, y no un objeto real, por lo que no está sujeto a las mismas restricciones de definición recursiva.