¿Cómo evita el `System.Boolean` de mscorlib los ciclos de diseño de estructura?

10

El código System.Booleanfuente del sitio web de la Fuente de referencia establece que las instancias struct Booleancontienen solo un boolcampo private bool m_value:

https://referencesource.microsoft.com/#mscorlib/system/boolean.cs,f1b135ff6c380b37

namespace System {

    using System;
    using System.Globalization;
    using System.Diagnostics.Contracts;

    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    public struct Boolean : IComparable, IConvertible
#if GENERICS_WORK
        , IComparable<Boolean>,  IEquatable<Boolean>
#endif
    {
      private bool m_value;

      internal const int True = 1; 
      internal const int False = 0; 

      internal const String TrueLiteral  = "True";
      internal const String FalseLiteral = "False";

      public static readonly String TrueString  = TrueLiteral;
      public static readonly String FalseString = FalseLiteral;
}

Pero me di cuenta de que ...

  • booles un alias de lenguaje C # para System.Boolean.
  • El tipo es el struct Booleanque es un tipo de valor, lo que significa que no puede contenerse como un campo .
  • ... sin embargo, este código probablemente compila.
  • Yo entiendo que cuando la -nostdlibopción del compilador se establece lo necesario para proporcionar a sus propios esenciales definiciones de tipos como System.String, System.Int32, System.Exception- esa es la única diferencia.
  • El código fuente publicado no contiene otros atributos especiales como [MethodImpl( MethodImplOptions.InternalCall )].

Entonces, ¿cómo se compila este código?

Dai
fuente
1
Es una demostración decente de que el supuesto común de "es un alias" es un modelo mental roto. booles una palabra clave en el lenguaje C #. Tanto el compilador como el tiempo de ejecución tienen mucho conocimiento incorporado sobre el tipo y no necesitan ayuda de System.Boolean. Las declaraciones en mscorlib para los tipos de valores primitivos coinciden con la representación en recuadro del tipo.
Hans Passant

Respuestas:

3

Respuesta corta : es un caso especial, relacionado con el boxeo de tipo y su representación subyacente. Estos tipos son bien conocidos por el compilador y, como tales, son tratados de manera ligeramente diferente por las partes centrales del tiempo de ejecución y el compilador / optimizador JIT en comparación con los tipos normales.


Dado que esto está profundamente oculto en la implementación del tiempo de ejecución, supongo que la especificación del lenguaje no entraría en detalles específicos de la implementación del tiempo de ejecución. No estoy seguro de si esta es una respuesta lo suficientemente satisfactoria, pero creo que en este caso particular, el booltipo permanece sin caja y, por lo tanto, existe como un tipo de valor bruto como parte de la estructura.

La semántica del boxeo y el desempaquetado de los tipos de valores son intencionalmente opacos para facilitar el uso del lenguaje. En este caso, la Booleanestructura misma parece depender de reglas de boxeo específicas de implementación para implementar la semántica real, como:

  // Determines whether two Boolean objects are equal.
  public override bool Equals (Object obj) {
    //If it's not a boolean, we're definitely not equal
    if (!(obj is Boolean)) {
      return false;
    }

    return (m_value==((Boolean)obj).m_value);
  }

Creo en lo anterior, una estructura en recuadro que representa un tipo booleano se verifica primero, luego se desempaqueta y boolse compara directamente el valor interno . A diferencia de un tipo en caja, que puede ser un puntero etiquetado o una estructura real con alguna información de tipo de tiempo de ejecución, los tipos sin caja se tratan como datos reales.

Creo internamente, si un bool tuviera que ser encasillado para System.Objectque se haga pasar por (debido a la eliminación de tipo o donde no sea posible la optimización), terminaría con algo similar a esto para el truecual el valor de los cuadros 1.

ldc.i4.1
box        [mscorlib]System.Boolean

Entonces, mientras que en un nivel alto booly System.Booleanparece ser idéntico y puede optimizarse de manera similar, en este caso particular dentro del tiempo de ejecución, las distinciones entre las versiones en caja y sin caja boolestán directamente expuestas. De manera similar, un sin caja boolno se puede comparar con el System.Objectque es inherentemente un tipo con caja. Esta respuesta con respecto a la necesidad de boxeo / unboxing va mucho más allá en cuanto a explicar el principio mismo.

En los lenguajes administrados, las implementaciones de tiempo de ejecución generalmente deben estar exentas de ciertas reglas cuando se trata de algunas características principales de tiempo de ejecución, esto es cierto para Java y otros lenguajes basados ​​en JVM. Si bien tampoco estoy familiarizado con CLR, creo que el mismo principio se aplica aquí.

Si bien esta pregunta sobre 'bool' es un alias de tipo para 'System.Boolean' esencialmente cubre casos de uso general, al acercarse a la implementación en tiempo de ejecución, el dialecto de C # se parece más a "C # específico de implementación", que puede doblar ligeramente las reglas .

Kristina Brooks
fuente
Voté esto por su comprensión, pero no puedo marcarlo como la respuesta aceptada porque no tiene autoridad, lo siento :(
Dai