Instrukcje: badanie i tworzenie wystąpień typów ogólnych z odbiciem
Informacje o typach ogólnych są uzyskiwane w taki sam sposób jak informacje o innych typach: sprawdzając Type obiekt reprezentujący typ ogólny. Różnica w zasadzie polega na tym, że typ ogólny ma listę Type obiektów reprezentujących jego parametry typu ogólnego. Pierwsza procedura w tej sekcji analizuje typy ogólne.
Można utworzyć Type obiekt reprezentujący skonstruowany typ według argumentów typu powiązania do parametrów typu definicji typu ogólnego. Druga procedura pokazuje to.
Aby zbadać typ ogólny i jego parametry typu
Pobierz wystąpienie Type , które reprezentuje typ ogólny. W poniższym kodzie typ jest uzyskiwany przy użyciu operatora języka C#
typeof
(GetType
w Języku Visual Basictypeid
w języku Visual C++). Zapoznaj się z tematem klasy, Type aby uzyskać inne sposoby uzyskiwania Type obiektu. Należy pamiętać, że w pozostałej części tej procedury typ jest zawarty w parametrze metody o nazwiet
.Type^ d1 = Dictionary::typeid;
Type d1 = typeof(Dictionary<,>);
Dim d1 As Type = GetType(Dictionary(Of ,))
IsGenericType Użyj właściwości , aby określić, czy typ jest ogólny, i użyj IsGenericTypeDefinition właściwości , aby określić, czy typ jest definicją typu ogólnego.
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)
Pobierz tablicę zawierającą argumenty typu ogólnego przy użyciu GetGenericArguments metody .
array<Type^>^ typeParameters = t->GetGenericArguments();
Type[] typeParameters = t.GetGenericArguments();
Dim typeParameters() As Type = t.GetGenericArguments()
Dla każdego argumentu typu określ, czy jest to parametr typu (na przykład w definicji typu ogólnego) czy typ określony dla parametru typu (na przykład w skonstruowanym typie IsGenericParameter ), używając właściwości .
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
W systemie typów ogólny parametr typu jest reprezentowany przez wystąpienie Typeklasy , podobnie jak zwykłe typy. Poniższy kod wyświetla nazwę i położenie parametru Type obiektu, który reprezentuje parametr typu ogólnego. Pozycja parametru jest tutaj prostymi informacjami; Jest to bardziej interesujące podczas badania parametru typu, który został użyty jako argument typu innego typu ogólnego.
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)
Określ ograniczenie typu podstawowego i ograniczenia interfejsu parametru typu ogólnego przy użyciu GetGenericParameterConstraints metody w celu uzyskania wszystkich ograniczeń w jednej tablicy. Ograniczenia nie są gwarantowane w żadnej określonej kolejności.
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 Użyj właściwości , aby odnaleźć specjalne ograniczenia dla parametru typu, takie jak wymaganie, aby był to typ odwołania. Właściwość zawiera również wartości reprezentujące wariancję, które można zamaskować, jak pokazano w poniższym kodzie.
GenericParameterAttributes sConstraints = tp->GenericParameterAttributes & GenericParameterAttributes::SpecialConstraintMask;
GenericParameterAttributes sConstraints = tp.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
Dim sConstraints As GenericParameterAttributes = _ tp.GenericParameterAttributes And _ GenericParameterAttributes.SpecialConstraintMask
Specjalne atrybuty ograniczenia są flagami, a ta sama flaga (GenericParameterAttributes.None), która nie reprezentuje żadnych specjalnych ograniczeń, również nie reprezentuje kowariancji ani kontrawariancji. W związku z tym, aby przetestować jeden z tych warunków, należy użyć odpowiedniej maski. W tym przypadku użyj polecenia GenericParameterAttributes.SpecialConstraintMask , aby odizolować specjalne flagi ograniczeń.
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
Konstruowanie wystąpienia typu ogólnego
Typ ogólny jest podobny do szablonu. Nie można utworzyć wystąpień, chyba że określisz rzeczywiste typy dla jego ogólnych parametrów typu. Aby to zrobić w czasie wykonywania, użycie odbicia wymaga MakeGenericType metody .
Type Pobierz obiekt reprezentujący typ ogólny. Poniższy kod pobiera typ Dictionary<TKey,TValue> ogólny na dwa różne sposoby: przy użyciu Type.GetType(String) przeciążenia metody z ciągiem opisującym typ i wywołując GetGenericTypeDefinition metodę na skonstruowanym typie
Dictionary\<String, Example>
(Dictionary(Of String, Example)
w Visual Basic). Metoda MakeGenericType wymaga definicji typu ogólnego.// 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()
Skonstruuj tablicę argumentów typu, aby zastąpić parametry typu. Tablica musi zawierać prawidłową liczbę Type obiektów w takiej samej kolejności, jak na liście parametrów typu. W tym przypadku klucz (pierwszy parametr typu) jest typu String, a wartości w słowniku to wystąpienia klasy o nazwie
Example
.array<Type^>^ typeArgs = {String::typeid, Example::typeid};
Type[] typeArgs = {typeof(string), typeof(Example)};
Dim typeArgs() As Type = _ {GetType(String), GetType(Example)}
Wywołaj metodę MakeGenericType , aby powiązać argumenty typu z parametrami typu i skonstruować typ.
Type^ constructed = d1->MakeGenericType(typeArgs);
Type constructed = d1.MakeGenericType(typeArgs);
Dim constructed As Type = _ d1.MakeGenericType(typeArgs)
CreateInstance(Type) Użyj przeciążenia metody, aby utworzyć obiekt skonstruowanego typu. Poniższy kod przechowuje dwa wystąpienia
Example
klasy w wynikowymDictionary<String, Example>
obiekcie.Object^ o = Activator::CreateInstance(constructed);
object o = Activator.CreateInstance(constructed);
Dim o As Object = Activator.CreateInstance(constructed)
Przykład
Poniższy przykład kodu definiuje metodę DisplayGenericType
badania ogólnych definicji typów i skonstruowanych typów używanych w kodzie i wyświetlania ich informacji. Metoda DisplayGenericType
pokazuje, jak używać IsGenericTypewłaściwości , IsGenericParameteri GenericParameterPosition i GetGenericArguments metody .
W przykładzie zdefiniowano również metodę sprawdzania DisplayGenericParameter
parametru typu ogólnego i wyświetlania jego ograniczeń.
Przykładowy kod definiuje zestaw typów testów, w tym typ ogólny, który ilustruje ograniczenia parametrów typu i pokazuje sposób wyświetlania informacji o tych typach.
Przykład tworzy typ z Dictionary<TKey,TValue> klasy, tworząc tablicę argumentów typu i wywołując metodę MakeGenericType . Program porównuje Type obiekt skonstruowany przy użyciu z MakeGenericType obiektem uzyskanym Type przy użyciu typeof
(GetType
w Visual Basic), pokazując, że są one takie same. Podobnie program używa GetGenericTypeDefinition metody w celu uzyskania ogólnej definicji typu skonstruowanego typu i porównuje go z Type obiektem reprezentującym klasę Dictionary<TKey,TValue> .
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