mscorlibの `System.Boolean`は構造体のレイアウトサイクルをどのように回避しますか?


10

System.BooleanReference Sourceウェブサイトののソースコードは、のインスタンスにはstruct Boolean単一のboolフィールドのみが含まれると述べています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;
}

しかし、私はそれに気づきました...

  • boolあるC#言語の別名のためにSystem.Boolean
  • タイプはstruct Boolean値タイプであり、それ自体をフィールドとして含めることはできません
  • ...まだこのコードはおそらくコンパイルされます。
  • 私は時にあることを理解し-nostdlib、コンパイラオプションが設定されているあなたがあなた自身の提供する必要が不可欠のような型定義をSystem.StringSystem.Int32System.Exception-それが唯一の違いです。
  • 公開されたソースコードには、などの他の特別な属性は含まれていません[MethodImpl( MethodImplOptions.InternalCall )]

それでは、このコードはどのようにコンパイルされますか?


1
一般的な「それはエイリアスである」という仮定が壊れたメンタルモデルであることはまともなデモンストレーションです。 boolあるキーワード C#言語では。コンパイラとランタイムの両方に、型に関する多くの組み込みの知識があり、System.Booleanの助けを必要としません。mscorlibでのプリミティブ値型の宣言は、型のボックス化表現と一致します。
Hans Passant

回答:


3

短い答え:タイプボクシングとその基礎となる表現に関連する特別なケースです。これらのタイプはコンパイラーによく知られているため、ランタイムのコア部分とコンパイラー/ JITオプティマイザーでは、通常のタイプとは少し異なる方法で処理されます。


これはランタイム実装の奥深くに埋め込まれているので、言語仕様は特定のランタイム実装の詳細には含まれないと思います。これで十分かどうかboolはわかりませんが、この特定のケースでは、型はボックス化されていないため、構造の一部として生の値型として存在します。

値型のボックス化とボックス化解除のセマンティクスは、言語を使いやすくするために意図的に不透明です。この場合、Boolean構造自体は、次のような実際のセマンティクスを実装するために、実装固有のボクシングルールに依存しているようです。

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

上記を信じて、ブール型を表すボックス化された構造は、最初に型チェックされ、次にボックス化が解除され、内部bool値が直接比較されます。タグ付きポインタまたはいくつかの実行時型情報を持つ実際の構造体であるボックス型とは異なり、ボックス型は実際のデータとして扱われます。

私は内部的に、ブール値をボックス化する必要がある場合System.Object(型の消去または最適化が不可能なため)、この行に沿っtrueて値をボックス化することになります1

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

非常に高いレベルでながらboolSystem.Boolean同一であることが表示され、ランタイム内のこの特定のケースでは、同様に最適化することができる、のボックス化とアンボックス化バージョン間の違いがbool直接露出しています。同様に、ボックス化boolされてSystem.Objectいないものは、本質的にボックス化されたタイプと比較できません。ボクシング/アンボクシングの必要性に関するこの答えは、原理自体を説明する限り、はるかに深く入ります。

マネージ言語では、いくつかのコアランタイム機能に関して、ランタイム実装は一般に特定のルールを免除する必要があります。これは、Javaや他のJVMベースの言語には確かに当てはまります。CLRにも精通していませんが、ここでも同じ原則が適用されると思います。

一方で「ブール」「可能System.Boolean」のタイプの別名であることについては、この質問は、基本的に一般的なユースケースをカバーランタイム実装に近づいたときに、C#のの方言は少しルールを曲げることができ、より多くの「実装固有のC#の」のようになり。


私はあなたの洞察のためにこれを賛成しました-しかし、権威がないので、これを受け入れられた回答としてマークできません。申し訳ありません:(
Dai
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.