In che modo `System.Boolean` di mscorlib evita i cicli di layout di struct?


10

Il codice sorgente per System.Booleannel sito Web Fonte di riferimento afferma che le istanze del struct Booleancontengono solo un singolo 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;
}

Ma ho notato che ...

  • boolè un alias di linguaggio C # per System.Boolean.
  • Il tipo è struct Booleanquale è un tipo di valore, il che significa che non può contenere se stesso come campo .
  • ... eppure questo codice presumibilmente si compila.
  • Capisco che quando l' -nostdlibopzione del compilatore è impostato è necessario fornire i propri essenziali definizioni dei tipi piace System.String, System.Int32, System.Exception- questa è l'unica differenza.
  • Il codice sorgente pubblicato non contiene altri attributi speciali come [MethodImpl( MethodImplOptions.InternalCall )].

Quindi, come si compila questo codice?


1
È una dimostrazione decente che il presupposto comune "è un alias" è un modello mentale rotto. boolè una parola chiave nel linguaggio C #. Sia il compilatore che il runtime hanno molte conoscenze integrate sul tipo e non hanno bisogno dell'aiuto di System.Boolean. Le dichiarazioni in mscorlib per i tipi di valore primitivi corrispondono alla rappresentazione in box del tipo.
Hans Passant,

Risposte:


3

Risposta breve : è un caso speciale, relativo al tipo di boxe e alla sua rappresentazione sottostante. Questi tipi sono ben noti al compilatore e come tali sono trattati in modo leggermente diverso dalle parti principali del runtime e dall'ottimizzatore del compilatore / JIT rispetto ai tipi normali.


Poiché questo è sepolto in profondità nell'implementazione del runtime, presumo che le specifiche del linguaggio non andrebbero nei dettagli specifici dell'implementazione del runtime. Non sono sicuro che si tratti di una risposta abbastanza soddisfacente, ma penso che in questo caso particolare il booltipo rimanga privo di box e quindi esiste come tipo di valore non elaborato come parte della struttura.

La semantica del pugilato e del non boxing dei tipi di valore è intenzionalmente opaca per rendere più semplice l'utilizzo del linguaggio. In questo caso la Booleanstruttura stessa sembra basarsi su specifiche regole di boxe per implementare la semantica attuale come:

  // 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);
  }

Credo in quanto sopra, una struttura scatolata che rappresenta un tipo booleano viene prima controllata per tipo, seguita dal fatto che è unboxed e il boolvalore interno viene confrontato direttamente. A differenza di un tipo boxed, che può essere un puntatore con tag o una struttura effettiva con alcune informazioni sul tipo di runtime, i tipi unboxed vengono trattati come dati effettivi.

Credo internamente, se un bool dovesse essere inscatolato per essere annullato come System.Object(a causa della cancellazione del tipo o in cui non sarebbe possibile alcuna ottimizzazione), si finirebbe con qualcosa sulla falsariga di ciò per truecui inscatola il valore 1.

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

Quindi, mentre ad un livello elevato boole System.Booleansembrano essere identici e possono essere ottimizzati in modo simile, in questo caso particolare all'interno del runtime, le distinzioni tra le versioni boxed e unboxed boolvengono esposte direttamente. Allo stesso modo, un unboxed boolnon può essere paragonato al System.Objectquale è intrinsecamente un tipo boxed. Questa risposta sulla necessità di boxe / unboxing va molto più in profondità fino a spiegare il principio stesso.

Nelle implementazioni di runtime delle lingue gestite, in genere è necessario essere esenti da determinate regole quando si tratta di alcune funzionalità di runtime di base, questo è certamente vero per Java e altri linguaggi basati su JVM. Anche se non ho familiarità con CLR, penso che lo stesso principio applicato qui.

Mentre questa domanda su "bool" è un alias di tipo per "System.Boolean" riguarda essenzialmente i casi d'uso generali, quando ci si avvicina all'implementazione in runtime, il dialetto di C # diventa più simile a "implementazione specifica C #", che può piegare leggermente le regole .


Ho valutato questo per la tua intuizione, ma non posso contrassegnarlo come risposta accettata perché non è autorevole, scusa :(
Dai
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.