2009-12-05 10 views
123

C#では、次のような汎用メソッドに制約を置くことができます。C#でパラメータ制約のある汎用コンストラクタはありますか?

public class A { 

    public static void Method<T> (T a) where T : new() { 
     //...do something... 
    } 

} 

Tにパラメータを必要としないコンストラクタが必要であると指定します。私は、 "のような制約を追加する方法があるかどうか疑問に思っていますか?float[,]パラメータを持つコンストラクタが存在しますか?"

次のコードはコンパイルされません:

public class A { 

    public static void Method<T> (T a) where T : new(float[,] u) { 
     //...do something... 
    } 

} 

有用?

+0

可能重複[特定のパラメータを取るコンストラクタを持たなければならないためにジェネリック型を制限するには?](http://stackoverflow.com/questions/853703/how-to-constrain-generic-type-to -metust-have-a-construtor-that-takes-certain-param) – nawfal

答えて

115

あなたが見つけてきたように、あなたはこれを行うことはできません。私は、通常タイプTのオブジェクトを作成することができますデリゲートを供給し、回避策として

public class A { 

    public static void Method<T> (T a, Func<float[,], T> creator) { 
     //...do something... 
    } 

} 
+37

は、論理的理由でパラメータ化されたコンストラクタの制約がありますか、それともまだ言語に追加されていないものですか? –

+18

合意...'new(float、double)'、 'new(string)'などが必要です。 – SliverNinja

+8

@Sahuaginクラスから継承すると、コンストラクタは継承されていないため、コンストラクタが定義されています。しかし、すべてのクラスには空のパラメータコンストラクタがあります。 – Matthew

5

いいえ現時点で指定できるコンストラクタ制約は、引数なしのコンストラクタのみです。

39

このような構成はありません。空のコンストラクタ制約のみを指定できます。

ラムダメソッドでこの問題を回避します。

public static void Method<T>(Func<int,T> del) { 
    var t = del(42); 
} 

ユースケース

Method(x => new Foo(x)); 
+0

'Method'の中で' Foo'の作成を抽象化する方法はありませんか? –

+0

'Method'のユーザが' Method(x => new Foo()); '? 'ラムダがそうでなければならないことを保証するためにとにかくありますか? –

15

ここでは、私は個人的に非常に効果的見つけ、このための回避策です。一般的なパラメータ化されたコンストラクタの制約が何であるか考えてみると、それは実際には特定のシグネチャを持つ型とコンストラクタの間のマッピングです。このようなマッピングは、辞書を使用して作成できます。静的な「工場」クラスにこれらを入れて、あなたは、コンストラクタラムダ毎回の構築を心配することなく、様々な種類のオブジェクトを作成することができます。

public static class BaseTypeFactory 
{ 
    private delegate BaseType BaseTypeConstructor(int pParam1, int pParam2); 

    private static readonly Dictionary<Type, BaseTypeConstructor> 
    mTypeConstructors = new Dictionary<Type, BaseTypeConstructor> 
    { 
     { typeof(Object1), (pParam1, pParam2) => new Object1(pParam1, pParam2) }, 
     { typeof(Object2), (pParam1, pParam2) => new Object2(pParam1, pParam2) }, 
     { typeof(Object3), (pParam1, pParam2) => new Object3(pParam1, pParam2) } 
    }; 

、あなたの一般的な方法で、例えば:

public static T BuildBaseType<T>(...) 
     where T : BaseType 
    { 
     ... 
     T myObject = (T)mTypeConstructors[typeof(T)](value1, value2); 
     ... 
     return myObject; 
    } 
+1

なぜこれはダウンサムに値するのですか?私の経験ではとてもうまく動作します。 –

+1

私はこれを今使っています、私はそれが良いパターンだと思います。 Factoryパターンでうまく動作します。ありがとう! – Matthew

32

リフレクションを使用して汎用オブジェクトを作成する場合、型には正しいコンストラクタが宣言されている必要があります。そうでない場合は、例外がスローされます。コンストラクタのいずれかと一致する限り、引数を渡すことができます。

この方法で、テンプレートのコンストラクタに制約を設定することはできません。 コンストラクタが存在しない場合は、コンパイル時にエラーを受け取るのではなく、実行時に例外を処理する必要があります。

// public static object CreateInstance(Type type, params object[] args); 

// Example 1 
T t = (T)Activator.CreateInstance(typeof(T)); 
// Example 2 
T t = (T)Activator.CreateInstance(typeof(T), arg0, arg1, arg2, ...); 
// Example 3 
T t = (T)Activator.CreateInstance(typeof(T), (string)arg0, (int)arg1, (bool)arg2); 
関連する問題