4

C++ では、template宣言は (テンプレートの型を明示的に宣言しない限り) ヘッダー ファイルで行う必要があり、その理由は理解できます。

私が得られないのは、.cs調べるファイルがない場合に C# コンパイラがジェネリックをどのように処理できるかということです。CIL はプロセッサを集中的に使用する操作になるので、CIL を調べるとは思えません。メタデータから型情報を抽出できることは知っていますが、汎用関数のコードもエンコードされていると、実行可能ファイルが膨大な量になります。

繰り返しになりますが、コンパイラはジェネリックをどのように処理するのでしょうか?

4

3 に答える 3

9

C# コンパイラがジェネリック型を定義する .cs ファイルをコンパイルする方法について質問するのではなく、C# コンパイラが参照アセンブリで定義されたジェネリック型をどのように使用するかについて質問していると思います (「 .cs ファイル」)。

ジェネリック型とメンバーは、IL ではジェネリックとしてエンコードされます。クローズ ジェネリック型とメンバーは、実行時に jit コンパイラによって構築されます。したがって、あなたの質問に対する簡単な答えは、「C# コンパイラは、実行時に jit コンパイラにジェネリック型を構築させる IL を発行することによってジェネリック型を処理する」ということです。

于 2013-01-15T17:45:41.050 に答える
3

C# コンパイラはアセンブリから型に関するメタデータを読み取ります。IL を確認する必要はありません。リフレクションを使用して同様のコードを記述し、ジェネリック型を分析できます。

C# コンパイラには、メソッドの実装の内部を調べる理由もありません。

C# と Java のジェネリックと C++ のテンプレートの違いは何ですか? を確認してください。C# がメソッドの実装を知る必要がない理由 (C++ とは異なり) の同様の検索結果 - C# のすべての制約は、クラス/メソッド シグネチャから認識されます。

于 2013-01-15T17:39:39.863 に答える
2

私は物事をクリアしようとしましょう...

ジェネリックは、メタデータのパラメーターと制約を含む IL として保存されます。ジェネリック型も型であり、実行時にランタイム型に変換されます。これは、テンプレート型が存在せず、派生型のみが存在する C++ との主な違いです。C# では、ジェネリック型は DLL に存在しますが、派生型は (実行時に作成されるまで) 存在しません。

ただし、コンパイラが行うことはいくつかあります。たとえば、List.Add(T) がある場合、IL の署名はまさにそれです。ただし、呼び出すと、List.Add(Foo) をメソッドとして使用してメソッドを解決します。たとえば、IL では次のように表示されます (フィールドをロードする場合):

ldfld class [mscorlib]System.List`1<Foo> Bar::variable

「T」ではなく「Foo」がここにあることに注意してください。

また、ジェネリック定義で T に制約を設定すると、コンパイル時にメタデータに対してチェックされます。

この時点で、まったく異なるが関連するものを指摘したいと思います。C# は、(一般的に) 型を遅延生成することでパフォーマンスを向上させます。これも C++ とは大きく異なります。静的コンストラクターとそれらが呼び出されたときに実験すると、これが実際に動作していることがわかります。

于 2013-01-15T18:43:19.400 に答える