2017-07-28 7 views
2

私は以下のコードのように何かする必要がありますが、新しいT()は動作しません。それは "それは新しい()制約がないため、変数型Tのインスタンスを作成できません。メソッドのジェネリックオブジェクトをジェネリックにするにはどうすればよいですか?

public static T MapToBaseDropDown2<T>(this GenericDropDownData dd) where T : BaseDropDown 
{ 
    return new T() //FAILS 
    { 
     Id = dd.Id, 
     Description = dd.Description 
    }; 
} 

BaseDropDownはEntityFramework(最初のコード)がマッピングされたエンティティである3つのチャイルズの基本クラスであるので、できるだけ簡単に保つ方がよいです。

は、今では原因私が試したいくつかの実装に抽象的ではありませんが、可能であれば、それは次のようになります。 new()制約が常に最後に適用されなければならない

public class BaseDropDown<T> where T : SomeClass, new() 
{ 
} 

public class BaseDropDown 
{ 
    public int Id { get; set; } 
    public string Description { get; set; } 
} 
+0

Googleの "新しい制約" - 答えを見つける:https://docs.microsoft.com/en-us/ dotnet/csharp/language-reference/keywords/new-constraint – Chris

+0

'BaseDropDown'とは何ですか?それがどのように定義されているかを示してください。 – HimBromBeere

+1

これは、あなたの拡張メソッドが、コンストラクタ、または非publicコンストラクタ、または必須パラメータを持つコンストラクタを持たないクラスに適用される可能性があるからです。 'new()'制約を使うと、あなたのメソッドを使っているインスタンスは、パラメータを持たないpublicコンストラクタを持つことになります。 – 0xaryan

答えて

2

これもちょうど(ないBaseDropDownに)Tに直接new()制約を追加して、作品

public static T MapToBaseDropDown3<T>(this GenericDropDownData dd) where T : BaseDropDown, new() 
{ 
    return new T() 
    { 
     Id = dd.Id, 
     Description = dd.Description 
    }; 
} 
1

BaseDropDownクラスは次のように適用されるnew()制約を持っている必要があります。詳細はhereを参照してください。リフレクションを使用して

+1

BaseDropDown' doesn'tある一般的なように見えるが、何BaseDropDown追加しました。 – HimBromBeere

-1

が正常に動作します:

public static T MapToBaseDropDown2<T>(this GenericDropDownData dd) where T : BaseDropDown 
{ 
    T entityDd = (T)Activator.CreateInstance(typeof(T)); 
    entityDd.Id = dd.Id; 
    entityDd.Description = dd.Description; 
    return entityDd; 
} 
+1

この手法ではなく、 'new()'制約を使うべきです。そうすれば、パラメータのないコンストラクタがない 'T 'でこれを試してみると、** compile **時に失敗します。あなたのコードはうまくコンパイルされますが、**実行**時には失敗します。 – mjwills

+0

あなたは正しいです、ありがとう –

2

new T()を呼び出すと、すべてのタイプがここの場合のように見えるdoesn'tパラメータなしコンストラクタを持っていることを前提としています。お使いのベースクラスBaseDropDownは、特定の抽象もので、そのすべてのサブクラスのためguranteed isn'tなコンストラクタを持っている場合でも:

class BaseDropDown 
{ 
    public BaseDropDown() { /* see parameterless-constructor exists */ } 
} 
abstract class MyClass : BaseDropDown 
{ 
    public MyClass() { ... } 
} 

今、あなたはnew -constraintを使用することができ抽象クラスを除外

public static T MapToBaseDropDown2<T>(this GenericDropDownData dd) where T : BaseDropDown, new() 

という制約はonlx BaseDropDownは、パラメータなしのコンストラクタを使ってインスタンス化されている継承するクラスを許可します。

関連する問題