如何:使用反映檢查和具現化泛型型別
取得泛型型別相關資訊的方式和取得其他類型相關資訊的方式一樣:檢查代表泛型型別的 Type 物件。 主要差異是泛型型別有代表其泛型型別參數的 Type 物件清單。 本節的第一個程序是檢查泛型型別。
您可以將型別引數繫結至泛型型別定義的型別參數,建立代表建構類型的 Type 物件。 第二個程序即示範此作業。
檢查泛型型別及其型別參數
取得表示泛型型別的 Type 執行個體。 在下列程式碼中,類型是使用 C#
typeof
運算子取得 (Visual Basic 為GetType
,Visual C++ 為typeid
)。 請參閱 Type 類別主題了解取得 Type 物件的其他方法。 請注意,在此程序的其餘部分中,類型是包含在名為t
的方法參數中。Type^ d1 = Dictionary::typeid;
Type d1 = typeof(Dictionary<,>);
Dim d1 As Type = GetType(Dictionary(Of ,))
使用 IsGenericType 屬性判斷類型是否為泛型,使用 IsGenericTypeDefinition 屬性判斷類型是否為泛型型別定義。
Console::WriteLine(" Is this a generic type? {0}", t->IsGenericType); Console::WriteLine(" Is this a generic type definition? {0}", t->IsGenericTypeDefinition);
Console.WriteLine(" Is this a generic type? {0}", t.IsGenericType); Console.WriteLine(" Is this a generic type definition? {0}", t.IsGenericTypeDefinition);
Console.WriteLine(" Is this a generic type? " _ & t.IsGenericType) Console.WriteLine(" Is this a generic type definition? " _ & t.IsGenericTypeDefinition)
使用 GetGenericArguments 方法取得包含泛型型別引數的陣列。
array<Type^>^ typeParameters = t->GetGenericArguments();
Type[] typeParameters = t.GetGenericArguments();
Dim typeParameters() As Type = t.GetGenericArguments()
每個型別引數都要使用 IsGenericParameter 屬性判斷它是型別參數 (例如,在泛型型別定義中),還是已針對型別參數指定的類型 (例如,在建構的類型中)。
Console::WriteLine(" List {0} type arguments:", typeParameters->Length); for each( Type^ tParam in typeParameters ) { if (tParam->IsGenericParameter) { DisplayGenericParameter(tParam); } else { Console::WriteLine(" Type argument: {0}", tParam); } }
Console.WriteLine(" List {0} type arguments:", typeParameters.Length); foreach( Type tParam in typeParameters ) { if (tParam.IsGenericParameter) { DisplayGenericParameter(tParam); } else { Console.WriteLine(" Type argument: {0}", tParam); } }
Console.WriteLine(" List {0} type arguments:", _ typeParameters.Length) For Each tParam As Type In typeParameters If tParam.IsGenericParameter Then DisplayGenericParameter(tParam) Else Console.WriteLine(" Type argument: {0}", _ tParam) End If Next
在型別系統中,泛型型別參數是由 Type 執行個體表示,就像一般的類型一 樣。 下列程式碼會顯示表示泛型型別參數之 Type 物件的名稱和參數位置。 參數位置在此為一般的資訊,但當您檢查曾用為其他泛型型別之型別引數的型別參數時,它就很有意思了。
static void DisplayGenericParameter(Type^ tp) { Console::WriteLine(" Type parameter: {0} position {1}", tp->Name, tp->GenericParameterPosition);
private static void DisplayGenericParameter(Type tp) { Console.WriteLine(" Type parameter: {0} position {1}", tp.Name, tp.GenericParameterPosition);
Private Shared Sub DisplayGenericParameter(ByVal tp As Type) Console.WriteLine(" Type parameter: {0} position {1}", _ tp.Name, tp.GenericParameterPosition)
使用 GetGenericParameterConstraints 方法取得單一陣列中的所有條件約束,來判斷泛型型別參數的基底類型條件約束和介面條件約束。 條件約束不保證任何特定順序。
Type^ classConstraint = nullptr; for each(Type^ iConstraint in tp->GetGenericParameterConstraints()) { if (iConstraint->IsInterface) { Console::WriteLine(" Interface constraint: {0}", iConstraint); } } if (classConstraint != nullptr) { Console::WriteLine(" Base type constraint: {0}", tp->BaseType); } else Console::WriteLine(" Base type constraint: None");
Type classConstraint = null; foreach(Type iConstraint in tp.GetGenericParameterConstraints()) { if (iConstraint.IsInterface) { Console.WriteLine(" Interface constraint: {0}", iConstraint); } } if (classConstraint != null) { Console.WriteLine(" Base type constraint: {0}", tp.BaseType); } else { Console.WriteLine(" Base type constraint: None"); }
Dim classConstraint As Type = Nothing For Each iConstraint As Type In tp.GetGenericParameterConstraints() If iConstraint.IsInterface Then Console.WriteLine(" Interface constraint: {0}", _ iConstraint) End If Next If classConstraint IsNot Nothing Then Console.WriteLine(" Base type constraint: {0}", _ tp.BaseType) Else Console.WriteLine(" Base type constraint: None") End If
使用 GenericParameterAttributes 屬性探索型別參數上的特殊條件約束,例如需要它為參考型別。 屬性也包含代表差異的值,您可以關閉遮罩,如下列程式碼所示。
GenericParameterAttributes sConstraints = tp->GenericParameterAttributes & GenericParameterAttributes::SpecialConstraintMask;
GenericParameterAttributes sConstraints = tp.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
Dim sConstraints As GenericParameterAttributes = _ tp.GenericParameterAttributes And _ GenericParameterAttributes.SpecialConstraintMask
特殊條件約束屬性是旗標,而不代表任何特殊條件約束的相同旗標 (GenericParameterAttributes.None),也不代表任何共變數或反變數。 因此,若要測試任一條件,您必須使用適當的遮罩。 本例使用 GenericParameterAttributes.SpecialConstraintMask 隔離特殊條件約束旗標。
if (sConstraints == GenericParameterAttributes::None) { Console::WriteLine(" No special constraints."); } else { if (GenericParameterAttributes::None != (sConstraints & GenericParameterAttributes::DefaultConstructorConstraint)) { Console::WriteLine(" Must have a parameterless constructor."); } if (GenericParameterAttributes::None != (sConstraints & GenericParameterAttributes::ReferenceTypeConstraint)) { Console::WriteLine(" Must be a reference type."); } if (GenericParameterAttributes::None != (sConstraints & GenericParameterAttributes::NotNullableValueTypeConstraint)) { Console::WriteLine(" Must be a non-nullable value type."); } }
if (sConstraints == GenericParameterAttributes.None) { Console.WriteLine(" No special constraints."); } else { if (GenericParameterAttributes.None != (sConstraints & GenericParameterAttributes.DefaultConstructorConstraint)) { Console.WriteLine(" Must have a parameterless constructor."); } if (GenericParameterAttributes.None != (sConstraints & GenericParameterAttributes.ReferenceTypeConstraint)) { Console.WriteLine(" Must be a reference type."); } if (GenericParameterAttributes.None != (sConstraints & GenericParameterAttributes.NotNullableValueTypeConstraint)) { Console.WriteLine(" Must be a non-nullable value type."); } }
If sConstraints = GenericParameterAttributes.None Then Console.WriteLine(" No special constraints.") Else If GenericParameterAttributes.None <> (sConstraints And _ GenericParameterAttributes.DefaultConstructorConstraint) Then Console.WriteLine(" Must have a parameterless constructor.") End If If GenericParameterAttributes.None <> (sConstraints And _ GenericParameterAttributes.ReferenceTypeConstraint) Then Console.WriteLine(" Must be a reference type.") End If If GenericParameterAttributes.None <> (sConstraints And _ GenericParameterAttributes.NotNullableValueTypeConstraint) Then Console.WriteLine(" Must be a non-nullable value type.") End If End If
建構泛型類型的實例
泛型型別就像範本。 除非指定其泛型型別參數的真實類型,否則無法建立它的執行個體。 若要在執行階段使用反映執行這項操作,需要 MakeGenericType 方法。
取得表示泛型型別的 Type 物件。 下列程式碼以兩種方式取得泛型型別 Dictionary<TKey,TValue>:使用 Type.GetType(String) 方法多載及描述類型的字串,以及在建構的類型
Dictionary\<String, Example>
(Visual Basic 為Dictionary(Of String, Example)
) 上呼叫 GetGenericTypeDefinition 方法。 MakeGenericType 方法需要泛型型別定義。// Use the typeid keyword to create the generic type // definition directly. Type^ d1 = Dictionary::typeid; // You can also obtain the generic type definition from a // constructed class. In this case, the constructed class // is a dictionary of Example objects, with String keys. Dictionary<String^, Example^>^ d2 = gcnew Dictionary<String^, Example^>(); // Get a Type object that represents the constructed type, // and from that get the generic type definition. The // variables d1 and d4 contain the same type. Type^ d3 = d2->GetType(); Type^ d4 = d3->GetGenericTypeDefinition();
// Use the typeof operator to create the generic type // definition directly. To specify the generic type definition, // omit the type arguments but retain the comma that separates // them. Type d1 = typeof(Dictionary<,>); // You can also obtain the generic type definition from a // constructed class. In this case, the constructed class // is a dictionary of Example objects, with String keys. Dictionary<string, Example> d2 = new Dictionary<string, Example>(); // Get a Type object that represents the constructed type, // and from that get the generic type definition. The // variables d1 and d4 contain the same type. Type d3 = d2.GetType(); Type d4 = d3.GetGenericTypeDefinition();
' Use the GetType operator to create the generic type ' definition directly. To specify the generic type definition, ' omit the type arguments but retain the comma that separates ' them. Dim d1 As Type = GetType(Dictionary(Of ,)) ' You can also obtain the generic type definition from a ' constructed class. In this case, the constructed class ' is a dictionary of Example objects, with String keys. Dim d2 As New Dictionary(Of String, Example) ' Get a Type object that represents the constructed type, ' and from that get the generic type definition. The ' variables d1 and d4 contain the same type. Dim d3 As Type = d2.GetType() Dim d4 As Type = d3.GetGenericTypeDefinition()
建構型別引數陣列來替代型別參數。 陣列必須包含正確的 Type 物件數,依型別參數清單中的出現順序排序。 本例中的索引鍵 (第一個型別參數) 類型是 String,字典中的值則是名為
Example
的類別執行個體。array<Type^>^ typeArgs = {String::typeid, Example::typeid};
Type[] typeArgs = {typeof(string), typeof(Example)};
Dim typeArgs() As Type = _ {GetType(String), GetType(Example)}
呼叫 MakeGenericType 方法將型別引數繫結至型別參數,並建構類型。
Type^ constructed = d1->MakeGenericType(typeArgs);
Type constructed = d1.MakeGenericType(typeArgs);
Dim constructed As Type = _ d1.MakeGenericType(typeArgs)
使用 CreateInstance(Type) 方法多載來建立建構類型的物件。 下列程式碼會將
Example
類別的兩個執行個體儲存在產生的Dictionary<String, Example>
物件中。Object^ o = Activator::CreateInstance(constructed);
object o = Activator.CreateInstance(constructed);
Dim o As Object = Activator.CreateInstance(constructed)
範例
下列程式碼範例會定義 DisplayGenericType
方法,檢查程式碼中的泛型型別定義和建構的類型,並顯示其相關資訊。 DisplayGenericType
方法示範如何使用 IsGenericType、IsGenericParameter 和 GenericParameterPosition 屬性以及 GetGenericArguments 方法。
此範例也會定義 DisplayGenericParameter
方法,檢查泛型型別參數,並顯示其條件約束。
程式碼範例會定義一組測試類型,包括說明型別參數條件約束的泛型型別,以及示範如何顯示這些類型的相關資訊。
此範例會建立型別引數陣列並呼叫 MakeGenericType 方法,從 Dictionary<TKey,TValue> 類別建構類型。 程式會比較使用 MakeGenericType 建構的 Type 物件和使用 typeof
(Visual Basic 為 GetType
) 取得的 Type 物件,示範它們是一樣的。 同樣地,程式會使用 GetGenericTypeDefinition 方法取得建構類型的泛型型別定義,和代表 Dictionary<TKey,TValue> 類別的 Type 物件相比較。
using namespace System;
using namespace System::Reflection;
using namespace System::Collections::Generic;
using namespace System::Security::Permissions;
// Define an example interface.
public interface class ITestArgument {};
// Define an example base class.
public ref class TestBase {};
// Define a generic class with one parameter. The parameter
// has three constraints: It must inherit TestBase, it must
// implement ITestArgument, and it must have a parameterless
// constructor.
generic<class T>
where T : TestBase, ITestArgument, gcnew()
public ref class Test {};
// Define a class that meets the constraints on the type
// parameter of class Test.
public ref class TestArgument : TestBase, ITestArgument
{
public:
TestArgument() {}
};
public ref class Example
{
// The following method displays information about a generic
// type.
private:
static void DisplayGenericType(Type^ t)
{
Console::WriteLine("\r\n {0}", t);
Console::WriteLine(" Is this a generic type? {0}",
t->IsGenericType);
Console::WriteLine(" Is this a generic type definition? {0}",
t->IsGenericTypeDefinition);
// Get the generic type parameters or type arguments.
array<Type^>^ typeParameters = t->GetGenericArguments();
Console::WriteLine(" List {0} type arguments:",
typeParameters->Length);
for each( Type^ tParam in typeParameters )
{
if (tParam->IsGenericParameter)
{
DisplayGenericParameter(tParam);
}
else
{
Console::WriteLine(" Type argument: {0}",
tParam);
}
}
}
// The following method displays information about a generic
// type parameter. Generic type parameters are represented by
// instances of System.Type, just like ordinary types.
static void DisplayGenericParameter(Type^ tp)
{
Console::WriteLine(" Type parameter: {0} position {1}",
tp->Name, tp->GenericParameterPosition);
Type^ classConstraint = nullptr;
for each(Type^ iConstraint in tp->GetGenericParameterConstraints())
{
if (iConstraint->IsInterface)
{
Console::WriteLine(" Interface constraint: {0}",
iConstraint);
}
}
if (classConstraint != nullptr)
{
Console::WriteLine(" Base type constraint: {0}",
tp->BaseType);
}
else
Console::WriteLine(" Base type constraint: None");
GenericParameterAttributes sConstraints =
tp->GenericParameterAttributes &
GenericParameterAttributes::SpecialConstraintMask;
if (sConstraints == GenericParameterAttributes::None)
{
Console::WriteLine(" No special constraints.");
}
else
{
if (GenericParameterAttributes::None != (sConstraints &
GenericParameterAttributes::DefaultConstructorConstraint))
{
Console::WriteLine(" Must have a parameterless constructor.");
}
if (GenericParameterAttributes::None != (sConstraints &
GenericParameterAttributes::ReferenceTypeConstraint))
{
Console::WriteLine(" Must be a reference type.");
}
if (GenericParameterAttributes::None != (sConstraints &
GenericParameterAttributes::NotNullableValueTypeConstraint))
{
Console::WriteLine(" Must be a non-nullable value type.");
}
}
}
public:
[PermissionSetAttribute(SecurityAction::Demand, Name="FullTrust")]
static void Main()
{
// Two ways to get a Type object that represents the generic
// type definition of the Dictionary class.
//
// Use the typeid keyword to create the generic type
// definition directly.
Type^ d1 = Dictionary::typeid;
// You can also obtain the generic type definition from a
// constructed class. In this case, the constructed class
// is a dictionary of Example objects, with String keys.
Dictionary<String^, Example^>^ d2 = gcnew Dictionary<String^, Example^>();
// Get a Type object that represents the constructed type,
// and from that get the generic type definition. The
// variables d1 and d4 contain the same type.
Type^ d3 = d2->GetType();
Type^ d4 = d3->GetGenericTypeDefinition();
// Display information for the generic type definition, and
// for the constructed type Dictionary<String, Example>.
DisplayGenericType(d1);
DisplayGenericType(d2->GetType());
// Construct an array of type arguments to substitute for
// the type parameters of the generic Dictionary class.
// The array must contain the correct number of types, in
// the same order that they appear in the type parameter
// list of Dictionary. The key (first type parameter)
// is of type string, and the type to be contained in the
// dictionary is Example.
array<Type^>^ typeArgs = {String::typeid, Example::typeid};
// Construct the type Dictionary<String, Example>.
Type^ constructed = d1->MakeGenericType(typeArgs);
DisplayGenericType(constructed);
Object^ o = Activator::CreateInstance(constructed);
Console::WriteLine("\r\nCompare types obtained by different methods:");
Console::WriteLine(" Are the constructed types equal? {0}",
(d2->GetType()==constructed));
Console::WriteLine(" Are the generic definitions equal? {0}",
(d1==constructed->GetGenericTypeDefinition()));
// Demonstrate the DisplayGenericType and
// DisplayGenericParameter methods with the Test class
// defined above. This shows base, interface, and special
// constraints.
DisplayGenericType(Test::typeid);
}
};
int main()
{
Example::Main();
}
using System;
using System.Reflection;
using System.Collections.Generic;
// Define an example interface.
public interface ITestArgument {}
// Define an example base class.
public class TestBase {}
// Define a generic class with one parameter. The parameter
// has three constraints: It must inherit TestBase, it must
// implement ITestArgument, and it must have a parameterless
// constructor.
public class Test<T> where T : TestBase, ITestArgument, new() {}
// Define a class that meets the constraints on the type
// parameter of class Test.
public class TestArgument : TestBase, ITestArgument
{
public TestArgument() {}
}
public class Example
{
// The following method displays information about a generic
// type.
private static void DisplayGenericType(Type t)
{
Console.WriteLine("\r\n {0}", t);
Console.WriteLine(" Is this a generic type? {0}",
t.IsGenericType);
Console.WriteLine(" Is this a generic type definition? {0}",
t.IsGenericTypeDefinition);
// Get the generic type parameters or type arguments.
Type[] typeParameters = t.GetGenericArguments();
Console.WriteLine(" List {0} type arguments:",
typeParameters.Length);
foreach( Type tParam in typeParameters )
{
if (tParam.IsGenericParameter)
{
DisplayGenericParameter(tParam);
}
else
{
Console.WriteLine(" Type argument: {0}",
tParam);
}
}
}
// The following method displays information about a generic
// type parameter. Generic type parameters are represented by
// instances of System.Type, just like ordinary types.
private static void DisplayGenericParameter(Type tp)
{
Console.WriteLine(" Type parameter: {0} position {1}",
tp.Name, tp.GenericParameterPosition);
Type classConstraint = null;
foreach(Type iConstraint in tp.GetGenericParameterConstraints())
{
if (iConstraint.IsInterface)
{
Console.WriteLine(" Interface constraint: {0}",
iConstraint);
}
}
if (classConstraint != null)
{
Console.WriteLine(" Base type constraint: {0}",
tp.BaseType);
}
else
{
Console.WriteLine(" Base type constraint: None");
}
GenericParameterAttributes sConstraints =
tp.GenericParameterAttributes &
GenericParameterAttributes.SpecialConstraintMask;
if (sConstraints == GenericParameterAttributes.None)
{
Console.WriteLine(" No special constraints.");
}
else
{
if (GenericParameterAttributes.None != (sConstraints &
GenericParameterAttributes.DefaultConstructorConstraint))
{
Console.WriteLine(" Must have a parameterless constructor.");
}
if (GenericParameterAttributes.None != (sConstraints &
GenericParameterAttributes.ReferenceTypeConstraint))
{
Console.WriteLine(" Must be a reference type.");
}
if (GenericParameterAttributes.None != (sConstraints &
GenericParameterAttributes.NotNullableValueTypeConstraint))
{
Console.WriteLine(" Must be a non-nullable value type.");
}
}
}
public static void Main()
{
// Two ways to get a Type object that represents the generic
// type definition of the Dictionary class.
//
// Use the typeof operator to create the generic type
// definition directly. To specify the generic type definition,
// omit the type arguments but retain the comma that separates
// them.
Type d1 = typeof(Dictionary<,>);
// You can also obtain the generic type definition from a
// constructed class. In this case, the constructed class
// is a dictionary of Example objects, with String keys.
Dictionary<string, Example> d2 = new Dictionary<string, Example>();
// Get a Type object that represents the constructed type,
// and from that get the generic type definition. The
// variables d1 and d4 contain the same type.
Type d3 = d2.GetType();
Type d4 = d3.GetGenericTypeDefinition();
// Display information for the generic type definition, and
// for the constructed type Dictionary<String, Example>.
DisplayGenericType(d1);
DisplayGenericType(d2.GetType());
// Construct an array of type arguments to substitute for
// the type parameters of the generic Dictionary class.
// The array must contain the correct number of types, in
// the same order that they appear in the type parameter
// list of Dictionary. The key (first type parameter)
// is of type string, and the type to be contained in the
// dictionary is Example.
Type[] typeArgs = {typeof(string), typeof(Example)};
// Construct the type Dictionary<String, Example>.
Type constructed = d1.MakeGenericType(typeArgs);
DisplayGenericType(constructed);
object o = Activator.CreateInstance(constructed);
Console.WriteLine("\r\nCompare types obtained by different methods:");
Console.WriteLine(" Are the constructed types equal? {0}",
(d2.GetType()==constructed));
Console.WriteLine(" Are the generic definitions equal? {0}",
(d1==constructed.GetGenericTypeDefinition()));
// Demonstrate the DisplayGenericType and
// DisplayGenericParameter methods with the Test class
// defined above. This shows base, interface, and special
// constraints.
DisplayGenericType(typeof(Test<>));
}
}
Imports System.Reflection
Imports System.Collections.Generic
' Define an example interface.
Public Interface ITestArgument
End Interface
' Define an example base class.
Public Class TestBase
End Class
' Define a generic class with one parameter. The parameter
' has three constraints: It must inherit TestBase, it must
' implement ITestArgument, and it must have a parameterless
' constructor.
Public Class Test(Of T As {TestBase, ITestArgument, New})
End Class
' Define a class that meets the constraints on the type
' parameter of class Test.
Public Class TestArgument
Inherits TestBase
Implements ITestArgument
Public Sub New()
End Sub
End Class
Public Class Example
' The following method displays information about a generic
' type.
Private Shared Sub DisplayGenericType(ByVal t As Type)
Console.WriteLine(vbCrLf & t.ToString())
Console.WriteLine(" Is this a generic type? " _
& t.IsGenericType)
Console.WriteLine(" Is this a generic type definition? " _
& t.IsGenericTypeDefinition)
' Get the generic type parameters or type arguments.
Dim typeParameters() As Type = t.GetGenericArguments()
Console.WriteLine(" List {0} type arguments:", _
typeParameters.Length)
For Each tParam As Type In typeParameters
If tParam.IsGenericParameter Then
DisplayGenericParameter(tParam)
Else
Console.WriteLine(" Type argument: {0}", _
tParam)
End If
Next
End Sub
' The following method displays information about a generic
' type parameter. Generic type parameters are represented by
' instances of System.Type, just like ordinary types.
Private Shared Sub DisplayGenericParameter(ByVal tp As Type)
Console.WriteLine(" Type parameter: {0} position {1}", _
tp.Name, tp.GenericParameterPosition)
Dim classConstraint As Type = Nothing
For Each iConstraint As Type In tp.GetGenericParameterConstraints()
If iConstraint.IsInterface Then
Console.WriteLine(" Interface constraint: {0}", _
iConstraint)
End If
Next
If classConstraint IsNot Nothing Then
Console.WriteLine(" Base type constraint: {0}", _
tp.BaseType)
Else
Console.WriteLine(" Base type constraint: None")
End If
Dim sConstraints As GenericParameterAttributes = _
tp.GenericParameterAttributes And _
GenericParameterAttributes.SpecialConstraintMask
If sConstraints = GenericParameterAttributes.None Then
Console.WriteLine(" No special constraints.")
Else
If GenericParameterAttributes.None <> (sConstraints And _
GenericParameterAttributes.DefaultConstructorConstraint) Then
Console.WriteLine(" Must have a parameterless constructor.")
End If
If GenericParameterAttributes.None <> (sConstraints And _
GenericParameterAttributes.ReferenceTypeConstraint) Then
Console.WriteLine(" Must be a reference type.")
End If
If GenericParameterAttributes.None <> (sConstraints And _
GenericParameterAttributes.NotNullableValueTypeConstraint) Then
Console.WriteLine(" Must be a non-nullable value type.")
End If
End If
End Sub
Public Shared Sub Main()
' Two ways to get a Type object that represents the generic
' type definition of the Dictionary class.
'
' Use the GetType operator to create the generic type
' definition directly. To specify the generic type definition,
' omit the type arguments but retain the comma that separates
' them.
Dim d1 As Type = GetType(Dictionary(Of ,))
' You can also obtain the generic type definition from a
' constructed class. In this case, the constructed class
' is a dictionary of Example objects, with String keys.
Dim d2 As New Dictionary(Of String, Example)
' Get a Type object that represents the constructed type,
' and from that get the generic type definition. The
' variables d1 and d4 contain the same type.
Dim d3 As Type = d2.GetType()
Dim d4 As Type = d3.GetGenericTypeDefinition()
' Display information for the generic type definition, and
' for the constructed type Dictionary(Of String, Example).
DisplayGenericType(d1)
DisplayGenericType(d2.GetType())
' Construct an array of type arguments to substitute for
' the type parameters of the generic Dictionary class.
' The array must contain the correct number of types, in
' the same order that they appear in the type parameter
' list of Dictionary. The key (first type parameter)
' is of type string, and the type to be contained in the
' dictionary is Example.
Dim typeArgs() As Type = _
{GetType(String), GetType(Example)}
' Construct the type Dictionary(Of String, Example).
Dim constructed As Type = _
d1.MakeGenericType(typeArgs)
DisplayGenericType(constructed)
Dim o As Object = Activator.CreateInstance(constructed)
Console.WriteLine(vbCrLf & _
"Compare types obtained by different methods:")
Console.WriteLine(" Are the constructed types equal? " _
& (d2.GetType() Is constructed))
Console.WriteLine(" Are the generic definitions equal? " _
& (d1 Is constructed.GetGenericTypeDefinition()))
' Demonstrate the DisplayGenericType and
' DisplayGenericParameter methods with the Test class
' defined above. This shows base, interface, and special
' constraints.
DisplayGenericType(GetType(Test(Of )))
End Sub
End Class