2011-06-30 36 views
109

你可以看到我想要什麼(但沒有),用下面的代碼做:C#創建新T()

protected T GetObject() 
{ 
    return new T(); 
} 

任何幫助將不勝感激。

編輯:

背景如下。我正在玩一個自定義控制器類,以便使用標準化方法從所有控制器派生出來。所以在上下文中,我需要創建控制器類型對象的新實例。所以在編寫時,它是這樣的:

public class GenericController<T> : Controller 
{ 
    ... 

    protected T GetObject() 
    { 
     return (T)Activator.CreateInstance(ObjectType); 
    }   

    public ActionResult Create() 
    { 
     var obj = GetObject() 

     return View(obj); 
    } 

所以我決定反射是最簡單的在這裏。我同意,當然,考慮到問題的初始陳述,標記爲正確的最合適的答案是使用new()約束的答案。我已經解決了這個問題。

+27

不,我沒有看到你想要什麼,並沒有做。我看到一段代碼可能是工作程序的一部分,沒有上下文,沒有錯誤信息,也沒有解釋。 –

+17

唉,我討厭它,當選擇錯誤的答案! –

+1

請添加上下文。 – James

回答

305

看看new Constraint

public class MyClass<T> where T : new() 
{ 
    protected T GetObject() 
    { 
     return new T(); 
    } 
} 

T可能是因爲沒有一個默認的構造函數的類:在這種情況下new T()將是一個無效的語句。 new()約束表示T必須具有默認構造函數,這使得new T()合法。

您可以將相同的約束泛型方法:

public static T GetObject<T>() where T : new() 
{ 
    return new T(); 
} 

如果你需要傳遞參數:

protected T GetObject(params object[] args) 
{ 
    return (T)Activator.CreateInstance(typeof(T), args); 
} 
+2

謝謝,夥計 - 我很高興今天學到了這一點。鑑於我的方法背景,我已經選擇了反射解決方案。乾杯! – Hanshan

+8

@nulliusinverba - 嗯......如果你在問題中展示了你的方法的上下文,那將會很好。 –

+1

@nulliusinverba - 你沒有在問題中顯示你需要參數。 –

27

另一種方法是使用反射:

protected T GetObject<T>(Type[] signature, object[] args) 
{ 
    return (T)typeof(T).GetConstructor(signature).Invoke(args); 
} 
+0

謝謝,隊友 - 我給這個解決方案給出了方法的上下文。 – Hanshan

+21

就像一個參考,這可以另外寫成Activator.CreateInstance(typeof(T),簽名,參數);有關更多詳細信息,請參閱http://msdn.microsoft.com/en-us/library/4b0ww1we.aspx。 –

+0

@Calgary編碼器:類型[]簽名有什麼用,你可以直接調用CreateInstance和params,而不需要明確地指定簽名。在這兩種情況下,如果匹配的構造函數不存在,您將得到MissingMethodException。 –

18

爲了完成,這裏最好的解決方案通常需要一個工廠函數參數:

T GetObject<T>(Func<T> factory) 
{ return factory(); } 

,並調用它是這樣的:

string s = GetObject(() => "result"); 

您可以使用要求或利用現有的參數,如果需要的話。

12

new constraint是好的,但如果你需要T是值類型也使用此:

protected T GetObject() { 
    if (typeof(T).IsValueType || typeof(T) == typeof(string)) { 
     return default(T); 
    } else { 
     return (T)Activator.CreateInstance(typeof(T)); 
    } 
} 
7

由於這是標記C#4,隨着開放sourece框架ImpromptuIntereface它將使用dlr調用構造函數,當你的構造函數有參數時,它比Activator快得多,而當它不具有參數時會慢得多。然而,主要優點是它將正確地處理帶有C#4.0可選參數的構造函數,這是Activator不會做的。

protected T GetObject(params object[] args) 
{ 
    return (T)Impromptu.InvokeConstructor(typeof(T), args); 
} 
4

爲了得到這個我想下面的代碼:

protected T GetObject<T>() 
    { 
     T obj = default(T); 
     obj =Activator.CreateInstance<T>(); 
     return obj ; 
    }