[英]Create a new instance of T without the new constraint
如果想要創建泛型的新實例,則需要定義新約束 ,如下所示:
public T SomeMethod<T>() where T : new()
{
return new T();
}
是否可以使用反射在沒有新約束的情況下創建T的實例,如此(包含偽代碼):
public T SomeMethod<T>()
{
if (T has a default constructor)
{
return a new instance of T;
}
else
{
return Factory<T>.CreateNew();
}
}
為此使用Activator.CreateInstance()
。 有關如何使用此方法的詳細信息,請參閱http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx 。 基本上,你做的是:
var obj = (T)Activator.CreateInstance(typeof(T));
您可以使用GetConstructors()
方法驗證它是否具有默認構造函數:
var constructors = typeof(T).GetConstructors();
如果找到參數為零的構造函數,則可以使用Activator.CreateInstance
方法。 否則,您使用Factory<T>.CreateNew()
方法。
編輯:
要直接找出沒有任何參數的構造函數,可以使用以下檢查:
if (typeof(T).GetConstructor(Type.EmptyTypes) != null)
{
// ...
具有where T : new()
約束的通用方法通過調用Activator.CreateInstance<T>()
實現new T()
調用。 關於這個方法的一個有趣的事情是它不包含約束 ,所以如果你很樂意將檢查推遲到運行時,只需使用:
public T SomeMethod<T>() {
return Activator.CreateInstance<T>();
}
這要么做什么return new T()
會做,或將引發一個有意義的異常。 因為它處理成功和失敗的情況,所以進行任何額外的檢查沒有任何實際好處,除非你想做一些模糊的事情,比如根本不使用構造函數 (可以這樣做)。
Marc Gravell答案的最后一句話(強調我的)
...除非你想做一些模糊的事情,比如根本不使用構造函數( 可以這樣做 )
從他對此的評論中,有另一種方法可以實現同樣的目的。 我不太清楚哪個是更好的表現 ,但老實說,我不在乎。 如果您想知道,請點擊該鏈接。 作者展示了一種混合方式。
使用System.Runtime.Serialization.FormatterServices.GetUninitializedObject()
(舊的MSDN文檔鏈接 )。
public static T SomeMethod<T>()
{
if (typeof(T) == typeof(string))
{
return default(T);
}
return (T)FormatterServices.GetUninitializedObject(typeof(T));
}
請注意string
的特殊注意。 沒有它, GetUninitializedObject()
將失敗。 這是來自MSDN在字符串上使用此方法:
它不會創建未初始化的字符串,因為創建不可變類型的空實例沒有任何意義。
它沒有說明它失敗的原因,而是更多關於它為什么會失敗的原因。 在此之后,還有另一個注釋如下:
您不能使用GetUninitializedObject方法來創建派生自ContextBoundObject類的類型的實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.