簡體   English   中英

在沒有新約束的情況下創建T的新實例

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM