Bagaimana cara `System.Boolean` mscorlib menghindari siklus tata letak struct?

10

Kode sumber untuk System.Booleandi situs web Sumber Referensi menyatakan bahwa instance struct Booleanhanya berisi boolbidang tunggal 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;
}

Tapi saya perhatikan bahwa ...

  • booladalah alias bahasa C # untuk System.Boolean.
  • Tipe ini struct Booleanadalah tipe nilai yang artinya tidak dapat memuat dirinya sendiri sebagai bidang .
  • ... namun kode ini mungkin dikompilasi.
  • Saya mengerti bahwa ketika -nostdlibopsi compiler diatur Anda perlu menyediakan Anda sendiri penting jenis definisi seperti System.String, System.Int32, System.Exception- itulah satu-satunya perbedaan.
  • Kode sumber yang dipublikasikan tidak mengandung atribut khusus seperti [MethodImpl( MethodImplOptions.InternalCall )].

Jadi bagaimana cara kompilasi kode ini?

Dai
sumber
1
Ini adalah demonstrasi yang layak bahwa asumsi umum "itu alias" adalah model mental yang rusak. booladalah kata kunci dalam bahasa C #. Baik kompiler dan runtime memiliki banyak pengetahuan bawaan tentang tipe dan tidak memerlukan bantuan dari System.Boolean. Deklarasi di mscorlib untuk tipe nilai primitif cocok dengan representasi kotak dari tipe tersebut.
Hans Passant

Jawaban:

3

Jawaban singkat : Ini adalah kasus khusus, berkaitan dengan jenis tinju dan representasi yang mendasarinya. Tipe-tipe ini dikenal baik oleh kompiler dan karena itu diperlakukan sedikit berbeda oleh bagian inti dari runtime dan kompiler / pengoptimal JIT dibandingkan dengan tipe biasa.


Karena ini tertanam jauh di dalam implementasi runtime, saya akan menganggap spesifikasi bahasa tidak akan masuk ke detail implementasi runtime tertentu. Saya tidak yakin apakah ini adalah jawaban yang cukup memuaskan tetapi saya pikir dalam kasus khusus ini, booltipe tersebut tetap terbuka dan dengan demikian ada sebagai tipe nilai mentah sebagai bagian dari struktur.

Semantik tinju dan unboxing jenis nilai sengaja buram untuk membuat menggunakan bahasa lebih mudah. Dalam hal ini Booleanstruktur itu sendiri tampaknya bergantung pada implementasi aturan tinju spesifik untuk mengimplementasikan semantik yang sebenarnya seperti:

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

Saya percaya pada hal di atas, struktur kotak yang mewakili tipe boolean adalah tipe-check pertama diikuti oleh itu sedang unboxed dan nilai internal boolyang langsung dibandingkan. Tidak seperti tipe kotak, yang mungkin merupakan penunjuk yang ditandai atau struktur aktual dengan beberapa informasi tipe runtime, tipe yang tidak kotak diperlakukan sebagai data aktual.

Saya percaya secara internal, jika bool harus dikotakkan untuk dilewati sebagai System.Object(karena penghapusan tipe atau di mana tidak ada optimasi akan mungkin) Anda akan berakhir dengan sesuatu di sepanjang garis ini trueyang kotak nilai 1.

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

Jadi, sementara pada tingkat tinggi booldan System.Booleantampak identik dan dapat dioptimalkan dengan cara yang sama, dalam kasus khusus ini di dalam runtime, perbedaan antara versi kotak dan tanpa kotak boolsecara langsung diekspos. Sama halnya, sebuah unboxed booltidak dapat dibandingkan dengan System.Objectyang secara inheren merupakan tipe boxed. Jawaban ini mengenai perlunya tinju / unboxing masuk jauh lebih mendalam sejauh menjelaskan prinsip itu sendiri.

Dalam implementasi runtime bahasa yang dikelola pada umumnya perlu dibebaskan dari aturan tertentu ketika datang ke beberapa fitur runtime inti, ini tentu berlaku untuk Java dan bahasa berbasis JVM lainnya. Meskipun saya tidak terbiasa dengan CLR juga, saya akan berpikir prinsip yang sama diterapkan di sini.

Sementara pertanyaan ini tentang 'bool' menjadi jenis alias untuk 'System.Boolean' pada dasarnya mencakup kasus penggunaan umum, ketika semakin dekat dengan implementasi runtime, dialek C # menjadi lebih seperti "implementasi spesifik C #", yang dapat sedikit membengkokkan aturan .

Kristina Brooks
sumber
Saya memilih ini untuk wawasan Anda - tetapi saya tidak dapat menandai ini sebagai jawaban yang diterima karena tidak otoritatif, maaf :(
Dai