2009-07-30 10 views
8

に比べて可能性の重複:
What are the differences between Generics in C# and Java… and Templates in C++?C#のジェネリックC++テンプレート

C++のテンプレートに比べて、C#のジェネリック医薬品との違いは何ですか?私は彼らがまったく同じ問題を解決しないことを理解しているので、両方の賛否両論は何ですか?

+4

今日の私のブログの話題は偶然です。 http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –

+1

これは正確に重複しています。 @エリック・リッパート:面白いですが、おもしろいですよね。 – jalf

答えて

16

あなたはジェネリックシステムを装った解釈、関数型プログラミング言語であることをC++のテンプレートを考慮することができます。これがあなたを怖がらせないならば、それはすべきです:

C#ジェネリックは非常に制限されています。型のクラスをパラメータ化し、それらの型をメソッドで使用することができます。だから、MSDNから例を取るために、あなたが行うことができます:

public class Stack<T> 
{ 
    T[] m_Items; 
    public void Push(T item) 
    {...} 
    public T Pop() 
    {...} 
} 

そして今ではでSomeOtherObjectを置くことについての(つまり、何も心配して安全に、あなたはStack<int>Stack<SomeObject>を宣言することはできませんし、それは、その型のオブジェクトを格納します間違い)。

内部的には、.NETランタイムは内部的に、int型などの基本型のバリアントとオブジェクト型のバリアントに特化します。これにより、Stack<byte>の表現は、例えば、Stack<SomeObject>の表現よりもはるかに小さくなります。

C++のテンプレートは、同様の使用を許可する:

template<typename T> 
class Stack 
{ 
    T *m_Items; 
    public void Push(const T &item) 
    {...} 
    public T Pop() 
    {...} 
}; 

これは一見似ていますが、いくつかの重要な違いがあります。まず、基本タイプごとに1つのバリアントとすべてのオブジェクトタイプに1つのバリアントの代わりに、それぞれに対してインスタンス化されたのバリアントが1つあります。それはたくさんの種類があります!

次の大きな違いは、(ほとんどのC++コンパイラでは)それが使用されている各翻訳単位でコンパイルされることです。これは多くのコンパイルを遅くする可能性があります。

C++のテンプレートのもう一つの興味深い属性は、クラス以外のものにも適用できます。そうであれば、引数が自動的に検出されます。例:

template<typename T> 
T min(const T &a, const T &b) { 
    return a > b ? b : a; 
} 

タイプTは、関数が使用されるコンテキストによって自動的に決定されます。

これらの属性は、あなたの正気を犠牲にして、良い終わりに使うことができます。 C++テンプレートは使用されている各タイプごとに再コンパイルされ、テンプレートの実装は常にコンパイラで使用できるため、C++はテンプレートに対して非常に積極的なインライン展開を実行できます。これに関数のテンプレート値の自動検出を追加し、boost::lambdaを使用してC++でanonymous pseudo-functionsを作成することができます。このように、表現のように:

_1 + _2 + _3

は、その引数を加算演算子を持っている真剣に怖いタイプ、()でオブジェクトを生成します。

C++テンプレートシステムには他にもたくさんの暗いコーナーがあります。非常に強力なツールですが、特に20ページの長いエラーメッセージが表示された場合には、考えるのが苦痛になることもあります。 C#システムははるかに簡単です - 強力ではありませんが、理解しやすく、悪用しにくいです。

+0

* C++のテンプレートのもう一つの興味深い属性は、クラス*以外のものにも適用できます。これはC#が関数でジェネリックを定義できるようにします(例えば 'T SomeFunc (T入力){...}' )? – dotNET

3

http://blogs.msdn.com/csharpfaq/archive/2004/03/12/88913.aspx

大雑把に、違いの多くは、テンプレートがコンパイル時に解決され、そしてジェネリックは実行時に解決されているという事実に関係しています。

+2

実際にジェネリックは実行時に(他の何かと同じように)リフレクションによってインスタンス化できますが、コンパイル時にジェネリックが分かります。たとえば、JITは 'List '(これはJavaとは異なる方法です)に相当する共通のタイプ消去バージョンを使用するのではなく、 'List 'の特定の実装を生成します。 –

+0

@Ewwicker:それについて教えてください。そのため、一般的な宣伝はできません(つまり、リストをリストに連結)。機能はCLIに存在しますが、C#でそのように実装しないことを選択しました(間違い、IMO)。 –

1

このblog entry from Eric Gunnersonは非常によく、このトピックをカバーしています。

最も大きな違いは、テンプレートはコンパイル時の機能であり、ジェネリックはランタイム機能であるという点です。スタックオーバーフローの

関連する問題