0

C++ ではジェネリクスが実際には存在しないことは知っていますが、. を使用してシミュレートできますtemplate。コードをビルドすると、コンパイラはコードを前処理し、オブジェクト宣言で指定された実際の値に置き換えられたジェネリック値を使用して新しいコードを生成します。次に、この新しいコードが実際にコンパイルされます。たとえば、A次のようなクラスがあるとします。

template<class T>
class A
{
    T f();
};

そして、私たちが持っているコードのどこか別の場所A<int> a;. コンパイルされる実際のコードは次のようになります。

class A
{
    //Replaces T by int in the pre-processing
    int f();
};

この全体の紹介の後、ポイントに行きましょう。

私の質問は次のとおりです。

  • C# はジェネリックを C++ と同じように扱いますか? そうでない場合、どのように?
  • 彼らは特別なタイプですか?
  • それらは実行時またはコンパイル時に解決されますか?
  • アクティベーション レジスタのジェネリック型用に予約されているスペースはどれくらいですか?
4

3 に答える 3

6

これは非常に幅広いトピックであり、次のように説明するとより適切に説明できます。

http://msdn.microsoft.com/en-us/library/c6cyy67b.aspx

要約するには (上記にリンクされている MSDN の記事から):

  • C# ジェネリックには、C++ テンプレートほどの柔軟性はありません。たとえば、ユーザー定義の演算子を呼び出すことはできますが、C# ジェネリック クラスで算術演算子を呼び出すことはできません。

  • C# では、テンプレート C {} などの型以外のテンプレート パラメーターは使用できません。

  • C# は明示的な特殊化をサポートしていません。つまり、特定の型のテンプレートのカスタム実装です。

  • C# は部分的な特殊化 (型引数のサブセットのカスタム実装) をサポートしていません。

  • C# では、型パラメーターをジェネリック型の基本クラスとして使用することはできません。

  • C# では、型パラメーターに既定の型を指定することはできません。

  • C# では、構築された型をジェネリックとして使用できますが、ジェネリック型パラメーター自体をジェネリックにすることはできません。C++ では、テンプレート パラメーターを使用できます。

  • C++ では、テンプレート内のすべての型パラメーターに対して有効ではない可能性のあるコードが許可され、型パラメーターとして使用される特定の型がチェックされます。C# では、制約を満たす任意の型で機能するようにクラス内のコードを記述する必要があります。たとえば、C++ では、型パラメーターのオブジェクトで算術演算子 + および - を使用する関数を作成できます。これらの演算子をサポートしない型でテンプレートをインスタンス化するときにエラーが発生します。C# はこれを許可しません。許可される唯一の言語構造は、制約から推測できるものです。

一般に、それらは同様の構文を共有し、ほとんどの場合に使用されますが、使用法と機能には多くの大きな違いがあります。

于 2013-03-22T05:22:13.813 に答える
3

C++ テンプレートの解決方法に関して誤解があります。C++ では、テンプレートは 2 回処理されます (注: 「前処理済み」という用語はプリプロセッサに予約されており、テンプレートとはまったく関係ありません)。

最初の処理時に、依存しない名前は解決されますが、依存する名前は解決されません。

int x;

template <typename T> foo() {
    x;    // <-- resolved in phase 1
    T::x; // resolved in phase 2, depends on "T"
}

インスタンス化すると、フェーズ 2 に入ります。例えば:

struct Frob {
    int x;
};

int main () {
    foo<Frob>();
} // <-- instantiation happens right before the '}'

また、C++ テンプレートは、関数ごとに遅延してインスタンス化されます。つまり、クラス テンプレート内のすべてが解決可能である必要はありません。実際に使用される関数のみがインスタンス化されます。つまり、フェーズ 2 は、使用されるメンバー関数に対してのみ入力されます。

これにより、テンプレートは C# スタイルのジェネリックよりも汎用性が高くなります。クラス テンプレートをインスタンス化する場合、インスタンス化された型はテンプレートのサブセットのみをサポートする必要があります。

C# では、ジェネリックは積極的に解決されます。「インスタンス化された」型は、ジェネリック クラスが使用する可能性のあるものだけをサポートする必要があり、汎用性にかなり厳しい制限が課されます。

ご存知のとおり、どちらもまったく異なる概念です。ジェネリックはランタイム コンストラクトであり、リフレクションと自己変更コードを使用するため、C# 言語解決可能性に関して非常に防御的でなければなりません。テンプレートはコンパイル時の構成要素 (注意: _preprocessing 構成要素ではありません!) であり、型引数と非型引数の両方を使用したチューリング完全なメタプログラミングと、熱心なインスタンス化と遅延インスタンス化の間の強力な妥協点をサポートします。

どちらにも特徴があります。

于 2013-03-22T05:30:12.357 に答える
1

.NET ジェネリックの実装は、いくつかの組み合わせです。

ジェネリック クラスが MSIL にコンパイルされると、単一のジェネリック型定義にコンパイルされます。

クライアントがジェネリック クラスを使用する場合、.NET ランタイムは単純な型パラメーター (bool、int など) のクラスのマシン コードの個別のコピーをコンパイルしますが、異なるオブジェクト型に対して個別のコードは生成されません。それらはすべて Object のコードを共有しています。

于 2013-03-22T05:23:06.143 に答える