Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Informace o obecných typech se získávají stejným způsobem jako informace o jiných typech: zkoumáním Type objektu, který představuje obecný typ. Hlavní rozdíl spočívá v tom, že obecný typ obsahuje seznam Type objektů představujících parametry obecného typu. První postup v této části zkoumá obecné typy.
Můžete vytvořit objekt Type, který představuje sestrojený typ vázáním argumentů typu na typové parametry obecné definice typu. Druhý postup to demonstruje.
Prozkoumání obecného typu a jeho parametrů typu
Získejte instanci Type, která představuje obecný typ. V následujícím kódu se typ získá pomocí operátoru jazyka C#
typeof(GetTypev jazyce Visual Basic). Další způsoby získání objektu Type naleznete v tématu Type. Ve zbývající části tohoto postupu je typ obsažen v parametru metody s názvemt.Type d1 = typeof(Dictionary<,>);Dim d1 As Type = GetType(Dictionary(Of ,))IsGenericType Pomocí vlastnosti určete, zda je typ obecný, a pomocí IsGenericTypeDefinition vlastnosti určit, zda typ je definice obecného typu.
Console.WriteLine($" Is this a generic type? {t.IsGenericType}"); Console.WriteLine($" Is this a generic type definition? {t.IsGenericTypeDefinition}");Console.WriteLine(" Is this a generic type? " _ & t.IsGenericType) Console.WriteLine(" Is this a generic type definition? " _ & t.IsGenericTypeDefinition)Pomocí metody získejte pole obsahující argumenty GetGenericArguments obecného typu.
Type[] typeParameters = t.GetGenericArguments();Dim typeParameters() As Type = t.GetGenericArguments()U každého argumentu typu určete, zda se jedná o parametr typu (například v definici obecného typu) nebo typ, který byl zadán pro parametr typu (například v konstruovaném typu), pomocí IsGenericParameter vlastnosti.
Console.WriteLine($" List {typeParameters.Length} type arguments:"); foreach (Type tParam in typeParameters) { if (tParam.IsGenericParameter) { DisplayGenericParameter(tParam); } else { Console.WriteLine($" Type argument: {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 NextV systému typů je obecný parametr typu reprezentován instancí Type, stejně jako běžné typy jsou. Následující kód zobrazí název a umístění parametru objektu Type , který představuje parametr obecného typu. Pozice parametru je zde triviální informace; je zajímavější, když zkoumáte parametr typu, který se používá jako argument typu jiného obecného typu.
Console.WriteLine($" Type parameter: {tp.Name} position {tp.GenericParameterPosition}");Private Shared Sub DisplayGenericParameter(ByVal tp As Type) Console.WriteLine(" Type parameter: {0} position {1}", _ tp.Name, tp.GenericParameterPosition)Pomocí metody GetGenericParameterConstraints určete omezení základního typu a omezení rozhraní obecného typu parametru a získejte všechna omezení v jediném poli. Omezení nejsou zaručena v žádném konkrétním pořadí.
foreach (Type iConstraint in tp.GetGenericParameterConstraints()) { if (iConstraint.IsInterface) { Console.WriteLine($" Interface constraint: {iConstraint}"); } } Console.WriteLine($" Base type constraint: {tp.BaseType ?? tp.BaseType: 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 IfGenericParameterAttributes Vlastnost použijte ke zjištění zvláštních omezení u parametru typu, jako je například vyžadování, aby se jedná o odkazový typ. Vlastnost také obsahuje hodnoty, které představují odchylku, které můžete maskovat, jak je znázorněno v následujícím kódu.
GenericParameterAttributes sConstraints = tp.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;Dim sConstraints As GenericParameterAttributes = _ tp.GenericParameterAttributes And _ GenericParameterAttributes.SpecialConstraintMaskSpeciální atributy omezení jsou příznaky a stejný příznak (GenericParameterAttributes.None), který neobsahuje žádná zvláštní omezení, také představuje žádnou kovarianci nebo kontravariance. Chcete-li tedy otestovat některou z těchto podmínek, musíte použít příslušnou masku. V tomto případě použijte GenericParameterAttributes.SpecialConstraintMask k izolaci příznaků speciálních omezení.
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
Vytvoření instance obecného typu
Obecný typ je jako šablona. Nelze vytvořit instance, pokud pro parametry obecného typu nezadáte skutečné typy. Pro použití reflexe za běhu je potřeba metoda MakeGenericType.
Type Získejte objekt, který představuje obecný typ. Následující kód získá obecný typ Dictionary<TKey,TValue> dvěma různými způsoby: buď použitím přetížení metody Type.GetType(String) s řetězcem, který popisuje typ, nebo voláním metody GetGenericTypeDefinition na již konstruovaný typ
Dictionary\<String, Example>(Dictionary(Of String, Example)v jazyce Visual Basic). Metoda MakeGenericType vyžaduje definici obecného typu.// 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 = []; // 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()Vytvořte pole argumentů typu, které nahradí parametry typu. Pole musí obsahovat správný počet Type objektů ve stejném pořadí, v jakém se zobrazují v seznamu parametrů typu. V tomto případě je klíč (první parametr typu) typu Stringa hodnoty ve slovníku jsou instancemi třídy s názvem
Example.Type[] typeArgs = [typeof(string), typeof(Example)];Dim typeArgs() As Type = _ {GetType(String), GetType(Example)}MakeGenericType Voláním metody vytvořte vazbu argumentů typu na parametry typu a sestavte typ.
Type constructed = d1.MakeGenericType(typeArgs);Dim constructed As Type = _ d1.MakeGenericType(typeArgs)CreateInstance(Type) Pomocí přetížení metody vytvořte objekt vytvořeného typu. Následující kód ukládá dvě instance
Exampletřídy do výslednéhoDictionary<String, Example>objektu._ = Activator.CreateInstance(constructed);Dim o As Object = Activator.CreateInstance(constructed)
Příklad
Následující příklad kódu definuje metodu DisplayGenericType pro zkoumání definic obecného typu a konstruovaných typů použitých v kódu a zobrazení jejich informací. Metoda DisplayGenericType ukazuje, jak používat IsGenericType, IsGenericParametera GenericParameterPosition vlastnosti a GetGenericArguments metoda.
Příklad také definuje metodu DisplayGenericParameter pro prozkoumání parametru obecného typu a zobrazení jeho omezení.
Příklad kódu definuje sadu typů testů, včetně obecného typu, který znázorňuje omezení parametru typu, a ukazuje, jak zobrazit informace o těchto typech.
Příklad vytvoří typ z Dictionary<TKey,TValue> třídy vytvořením pole argumentů typu a volání MakeGenericType metody. Program porovná objekt Type vytvořený pomocí MakeGenericType s objektem Type získaným pomocí typeof (GetType v jazyce Visual Basic), což demonstruje, že jsou stejné. Podobně program používá metodu GetGenericTypeDefinition k získání obecné definice typu vytvořeného typu a porovná ji s objektem Type představujícím Dictionary<TKey,TValue> třídu.
using System.Reflection;
// 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 {t}");
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.
Type[] typeParameters = t.GetGenericArguments();
Console.WriteLine($" List {typeParameters.Length} type arguments:");
foreach (Type tParam in typeParameters)
{
if (tParam.IsGenericParameter)
{
DisplayGenericParameter(tParam);
}
else
{
Console.WriteLine($" Type argument: {tParam}");
}
}
}
// Displays information about a generic type parameter.
private static void DisplayGenericParameter(Type tp)
{
Console.WriteLine($" Type parameter: {tp.Name} position {tp.GenericParameterPosition}");
foreach (Type iConstraint in tp.GetGenericParameterConstraints())
{
if (iConstraint.IsInterface)
{
Console.WriteLine($" Interface constraint: {iConstraint}");
}
}
Console.WriteLine($" Base type constraint: {tp.BaseType ?? tp.BaseType: 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 = [];
// 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);
_ = Activator.CreateInstance(constructed);
Console.WriteLine("\r\nCompare types obtained by different methods:");
Console.WriteLine($" Are the constructed types equal? {d2.GetType() == constructed}");
Console.WriteLine($" Are the generic definitions equal? {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