System.Type.MakeGenericType 方法
本文提供此 API 參考文件的補充備註。
MakeGenericType方法可讓您撰寫程序代碼,將特定類型指派給泛型型別定義的型別參數,從而建立Type代表特定建構型別的物件。 您可以使用這個 Type 物件來建立建構類型的運行時間實例。
使用 MakeGenericType 建構的型別可以開啟,也就是說,其某些型別自變數可以是封入泛型方法或型別的類型參數。 當您發出動態元件時,可能會使用這類開放式建構類型。 例如,請考慮類別 Base
,並在 Derived
下列程式代碼中。
public class Base<T, U> { }
public class Derived<V> : Base<int, V> { }
type Base<'T, 'U>() = class end
type Derived<'V>() = inherit Base<int, 'V>()
Public Class Base(Of T, U)
End Class
Public Class Derived(Of V)
Inherits Base(Of Integer, V)
End Class
若要在動態元件中產生 Derived
,必須建構其基底類型。 若要這樣做,請使用 泛型型別自變數Int32和 來自Derived
的型別參數V
,在代表 類別Base
的物件上Type呼叫 MakeGenericType 方法。 因為型別和泛型型別參數都是由 Type 物件表示,因此包含兩者的陣列都可以傳遞至 MakeGenericType 方法。
注意
這類 Base<int, V>
建構型別在發出程序代碼時很有用,但您無法在此類型上呼叫 MakeGenericType 方法,因為它不是泛型型別定義。 若要建立可具現化的封閉建構型別,請先呼叫 GetGenericTypeDefinition 方法以取得 Type 代表泛型型別定義的 對象,然後使用所需的型別自變數呼叫 MakeGenericType 。
Type傳MakeGenericType回的物件與Type呼叫GetType所產生建構型別之 方法所取得的物件相同,或是GetType使用相同型別自變數從相同泛型型別定義建立之任何建構型別的 方法。
注意
泛型型別的陣列本身不是泛型型別。 您無法在陣列類型上呼叫 MakeGenericType ,例如 C<T>[]
(Dim ac() As C(Of T)
在 Visual Basic 中)。 若要從 C<T>[]
建構封閉式泛型型別,請呼叫 GetElementType 以取得泛型型別定義;在泛型型別定義 C<T>
上呼叫 MakeGenericType 以建立建構型別;最後呼叫 MakeArrayType 建構型別上的 方法以建立數位類型。 指標類型和 ref
類型也是如此(ByRef
在 Visual Basic 中)。
如需泛型反映中所使用之規範的恆成立條件清單,請參閱 IsGenericType 屬性備註。
巢狀類型
如果使用 C#、C++ 或 Visual Basic 定義泛型類型,則其巢狀類型全都是泛型。 即使巢狀類型本身沒有類型參數,也是如此,因為這三種語言都會在巢狀類型的類型參數清單中包含封入型別的類型參數。 請考慮下列類別:
public class Outermost<T>
{
public class Inner<U>
{
public class Innermost1<V> {}
public class Innermost2 {}
}
}
Public Class Outermost(Of T)
Public Class Inner(Of U)
Public Class Innermost1(Of V)
End Class
Public Class Innermost2
End Class
End Class
End Class
巢狀類別 Inner
的類型參數清單有兩個型別參數, T
其中 U
第一個是其封入類別的類型參數。 同樣地,巢狀類別Innermost1
的類型參數清單有三個類型參數、 T
U
和 V
,以及 T
U
來自其封入類別。 巢狀類別 Innermost2
有兩個型別參數, T
和 U
,其來自其封入類別。
如果封入類型的參數清單有多個類型參數,則所有依序的類型參數都會包含在巢狀類型的類型參數清單中。
若要從巢狀型別的泛型型別定義建構泛型型別,請呼叫 MakeGenericType 方法,方法是串連所有封入型別的類型自變數數位,從最外層泛型型別開始,並以巢狀類型本身的類型自變數數組結尾,如果它有自己的類型參數。 若要建立的實例,請使用包含三種型別的 Innermost1
數位呼叫 MakeGenericType 方法,以指派給 T、U 和 V。若要建立的實例,請使用包含兩種型別的 Innermost2
數位呼叫 MakeGenericType 方法,以指派給 T 和 U。
語言會以這種方式傳播封入型別的類型參數,讓您可以使用封入類型的類型參數來定義巢狀類型的欄位。 否則,類型參數不會在巢狀類型的主體範圍內。 可以定義巢狀類型,而不傳播封入型別的類型參數、在動態元件中發出程式代碼或使用 Ilasm.exe (IL 元件器) 。 請考慮 CIL 組譯工具的下列程式代碼:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
在此範例中,無法定義 類型 T
或 U
類別 Innermost
中的欄位,因為這些類型參數不在範圍內。 下列組合器程式代碼會定義巢狀類別,這些類別的行為方式是在 C++、Visual Basic 和 C# 中定義:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
您可以使用 Ildasm.exe (IL 反組譯器) 來檢查高階語言中定義的巢狀類別,並觀察此命名配置。