2015-12-05 3 views
15

このような何かすることは有益であろう、なぜ私は理解に苦労している:ちょうど方法にサンプルを渡すようにする方が良いと思いませんか(サンプルはクラスである)メソッドのジェネリックのタイプを制限する目的は何ですか?

static void PrintResults<T>(T result) where T : Sample 

を?

static void PrintResults (Sample result) 
+6

メソッドに渡されるものについては、実際にはほんの僅かです。返されるものについては、消費者がキャストする必要がないため、もう少し役立ちます。 – Joey

答えて

10

あなたが指定した例のように、非汎用構文が機能するジェネリック型を避けることをおすすめします。しかし、他にも有用なケースがあります。

static T Create<T>() where T: Sample, new() 
{ 
    return new T(); 
} 

// Calling code 
Sample sample = Create<Sample>(); 

代わりにあなたはまた、タイプに複数の制約を配置するためのテンプレートを使用することができます

static object Create() 
{ 
    return new Sample(); 
} 

// Calling code 
Sample sample = (Sample) Create(); 

の:一般的に戻り値の型を指定するたとえば

、。たとえば:

static T Create<T>() where T: IMyInterface, new() 
{ 
    return new T(); 
} 

interface IMyInterface {} 
class MyClass : IMyInterface { } 

// Calling code. 
MyClass myClass = Create<MyClass>(); 

これは、特定のインターフェイスを実装し、一般的なコンストラクタを持つ新しいタイプの一般的な作成することができます。また:

あなたは(1)すべてのこれらのインタフェースを実装する新しいタイプを作成し、(2)その型にパラメータを必要とせずに単一のパラメータに複数のインタフェースを必要とし得る
static void DoSomething<T>(T t) where T: IMyInterface1, IMyInterface2 
{ 
    t.MethodOnIMyInterface1(); 
    t.MethodOnIMyInterface2(); 
} 

interface IMyInterface1 
{ 
    void MethodOnIMyInterface1(); 
}  
interface IMyInterface2 
{ 
    void MethodOnIMyInterface2(); 
}  
class MyClass: IMyInterface1, IMyInterface2 
{ 
    // Method implementations omitted for clarity 
} 

// Calling code 
MyClass myclass' 
DoSomething(myclass); // Note that the compiler infers the type of T. 

@dcastroが答えで指摘しているように、ジェネリック型は、コンパイラにタイプが同じであることを伝えることもできます。例えば:

static void DoSomething<T>(T t1, T t2) where T: MyType 
{ 
    // ... 
} 

class MyType {} 
class MyType1: MyType {} 
class MyType2: MyType {} 

// Calling code 
MyType1 myType1; 
MyType2 myType2; 
DoSomething<MyType>(myType1, myType2); 

コンパイラは、T1、T2は同じタイプであるが、MyTypeを継承する任意のタイプとすることができることを必要とする場合。これは、NUnitやMSTestなどの自動化された単体テストフレームワークで汎用的な等価性と比較チェックを行う場合に便利です。

+1

最後に、同じタイプを強制するビットが正しくありません。これらのうちのどれでも、DoSomething (mytype1、mytype2)というコンパイルだけでコンパイルできます。 DoSomething((MyType)mytype1、mytype2); '... – Brandon

+0

@aktonは詳細な答えをありがとう。私は実際に提供されたすべての答えを評価しました!私は仕事のための最良の例を挙げていませんでしたが、あなたはその質問にうまく答えていました。再度、感謝します! – Anonymous

+0

@Brandon問題は、物事がコンパイルされるかどうかではありません。 (1)コードを読みやすく(OPのケースではないが)、(2)実行時から(通常はキャストを置き換えることによって)よりコンパイル時間のチェックを移動する。特定のケースでは、これは最良の例ではありませんが、OPの質問に答えるのに十分です。 – akton

2

ボイドでは、複数の型を動作させるために、常にインターフェイスをパラメータとして使用することができるため、ここではジェネリックは役に立ちません。

例外はジェネリックの制約です。そしてそれによって私は何も意味しません ここでT:IA、IB これはインタフェースでも実行できるので、両方ともIAとIBを実装するためです。あなたがますます多くのインターフェースを必要とするので、これはいつか面倒なことになります。だから、ときジェネリック医薬品の本当の力がある「特別な制約」クラスATH見て、新しい

構造体

のための作業を習慣
public void AddNew(List<T> items) where T : new 
{ 
    items.Add(new T()); 
} 

及び方法は、パラメータを変異させる場合に有用であるクラス、

static void IncA<T>(T item) where T: class, IA 
{ 
    item.A++; 
} 

することができますメソッドには、リスト<T>のような一般的な戻り型または汎用クラスがあります。必要とするすべてのリストに対して新しいクラスを実装したくありません。

3

ほとんどの回答は、実際の質問に実際には対応していないようなインターフェースを含むジェネリックの有用性についての説明を提供しています。

真実は、あなたが投稿した例では、ジェネリックメソッドを使用する利点はありません。実際にはが悪いです。同じ関数の複数の実装が生成され、実行時にコードサイズがわずかに増加するためです。

+1

'Sample'は必然的に参照型であるため(実際には' class'であることを私たちに教えているので)、 'multiple implementation 'について言及したことは彼のケースには当てはまりません。参照型の場合、 "複数の実装"はありません。それ以外にも、彼の特別なシナリオではあまり効果がないかもしれません。特別な型 'T'(これは' typeof(T) 'が' result.GetType() 'と必ずしも同じではないコンパイル時型です)を取得します。このメソッドは、そのタイプを使用できます。たとえば、 'var config = HelperClass .GetConfig();'などです。 –

関連する問題