2017-07-28 46 views
2

我需要做財產以後像下面的代碼,但新T()不工作。它說 「因爲它不具有new()約束無法創建變量類型T的實例。」如何使通用方法的返回OBJECT?

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

BaseDropDown爲3名兒童的能與的EntityFramework(代碼第一)映射實體的基類,所以它可能是更好保持儘可能的簡單。

現在它不是抽象的,由於一些實現,我試過了,但如果可能的話會。

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

谷歌 「新約束」 - 找到答案:https://docs.microsoft.com/en-us/ dotnet/csharp/language-reference/keywords/new-constraint – Chris

+0

什麼是'BaseDropDown'?顯示它如何定義。 – HimBromBeere

+1

這是因爲您的擴展方法可能適用於沒有構造函數的類,非公共構造函數或具有必需參數的構造函數。使用'new()'約束,你可以確定使用你的方法的實例有一個沒有任何參數的公共構造函數。 – 0xaryan

回答

2

這也適用,只需直接添加new()約束T(不BaseDropDown)

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

BaseDropDown類需要應用這樣的new()約束:

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

new()約束必須始終是最後一個應用。有關更多詳情,請參閱here

+1

'BaseDropDown'似乎不是通用的,但是'MapToBaseDropDown2'是。 – 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

你應該使用'新()'約束,而不是這種技術。這樣,如果你嘗試用缺少無參數構造函數的'T'來執行此操作,它將在**編譯**時失敗。你的代碼可以很好地編譯,但是在**運行時會失敗。 – mjwills

+0

你是對的,謝謝 –

2

調用new T()假定每個類型無參數的構造函數,這doesn't似乎是這裏的情況。即使你的基類BaseDropDown有這樣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使用參數的構造函數是實例化類。

相關問題