56

楽しみのためだけに、.NET Framework Reference Sourceの .NET ソース コードを参照してきました。そして、わからないものを発見。

タイプの C# コードを含む Int32.csファイルがありますInt32。そして、どういうわけかそれは私には奇妙に思えます。C# コンパイラはどのようにInt32型のコードをコンパイルしますか?

public struct Int32: IComparable, IFormattable, IConvertible {
    internal int m_value;

    // ... 
}

しかし、これは C# では違法ではありませんか? intが の単なるエイリアスで ある場合、エラー CS0523Int32でコンパイルに失敗するはずです。

タイプ 'struct1' の構造体メンバー 'struct2 field' により、構造体レイアウトでサイクルが発生します。

コンパイラには魔法がありますか、それとも完全に軌道から外れていますか?

4

2 に答える 2

49

これは C# では違法ではありませんか? 「int」が「Int32」の単なるエイリアスである場合、エラー CS0523 でコンパイルに失敗するはずです。コンパイラに魔法はありますか?

はい; エラーはコンパイラで意図的に抑制されます。問題の型が組み込み型の場合、サイクル チェッカーは完全にスキップされます。

通常、この種のことは違法です。

struct S { S s; int i; }

その場合、S のサイズは未定義です。これは、S のサイズが何であれ、それ自体に int のサイズを加えた値に等しくなければならないためです。そのようなサイズはありません。

struct S { S s; }

その場合、S のサイズを推測するための情報はありません。

struct Int32 { Int32 i; }

ただし、この場合、コンパイラSystem.Int32はそれが非常に特殊な型であるため、4 バイトであることを事前に認識しています。

ちなみに、C# コンパイラ (さらに言えば、CLR) が構造体型のセットが循環型であるかどうかを判断する方法の詳細は、非常に興味深いものです。それについてはいつかブログ記事を書こうと思います。

于 2013-04-22T19:31:12.380 に答える
13

intのエイリアスですInt32が、Int32見ている構造体は単なるメタデータであり、実際のオブジェクトではありません。宣言は、構造体に適切なサイズを与えるためだけにある可能性があります。int m_valueこれは、実際には他の場所で参照されることはないためです (これが、そこに存在することが許可されている理由です)。

言い換えれば、コンパイラはこれを問題から救います。MSDN フォーラム で、このトピックに関するディスカッションが行われています。

議論から、宣言がどのように可能であるかを判断するのに役立つ、選択された回答からの引用を次に示します。

型に整数の m_value フィールドが含まれていることは事実ですが、フィールドは参照されません。すべてのサポート メソッド (CompareTo、ToString など) では、代わりに「this」が使用されます。m_value フィールドは、構造体に適切なサイズを強制するためだけに存在する可能性があります。

コンパイラが「int」を検出すると、それを「mscorlib.dll 内の System.Int32 への参照、後で解決する」に変換し、mscorlib.dll を構築しているため、循環参照 (ただし、m_value は使用されないため、問題を引き起こす可能性はありません)。この仮定が正しければ、このトリックは特殊なコンパイラ タイプに対してのみ機能します。

さらに読むと、構造体は単なるメタデータであり、実際のオブジェクトではないことがわかります。そのため、同じ再帰的定義の制約によって拘束されません。

于 2013-04-19T21:56:25.057 に答える