Type.MakeGenericType(Type[]) Metoda
Definice
Důležité
Některé informace platí pro předběžně vydaný produkt, který se může zásadně změnit, než ho výrobce nebo autor vydá. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Nahradí prvky pole typů parametry typu aktuální definice obecného typu a vrátí Type objekt představující výsledný vytvořený typ.
public:
abstract Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public:
virtual Type ^ MakeGenericType(... cli::array <Type ^> ^ typeArguments);
public abstract Type MakeGenericType(params Type[] typeArguments);
[System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")]
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public virtual Type MakeGenericType(params Type[] typeArguments);
public virtual Type MakeGenericType(params Type[] typeArguments);
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public virtual Type MakeGenericType(params Type[] typeArguments);
abstract member MakeGenericType : Type[] -> Type
[<System.Diagnostics.CodeAnalysis.RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")>]
[<System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")>]
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
[<System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")>]
abstract member MakeGenericType : Type[] -> Type
override this.MakeGenericType : Type[] -> Type
Public MustOverride Function MakeGenericType (ParamArray typeArguments As Type()) As Type
Public Overridable Function MakeGenericType (ParamArray typeArguments As Type()) As Type
Parametry
- typeArguments
- Type[]
Pole typů, které se mají nahradit parametry typu aktuálního obecného typu.
Návraty
A Type představující konstruovaný typ vytvořený nahrazením prvků typeArguments parametrů typu aktuálního obecného typu.
- Atributy
Výjimky
Aktuální typ nepředstavuje definici obecného typu. To znamená, IsGenericTypeDefinition že vrátí false.
Počet prvků není typeArguments stejný jako počet parametrů typu v aktuální definici obecného typu.
nebo
Jakýkoli prvek typeArguments nevyhovuje omezením zadaným pro odpovídající parametr typu aktuálního obecného typu.
nebo
typeArguments obsahuje prvek, který je typem ukazatele (IsPointer vrátí true), typ by-ref (IsByRef vrátí true) nebo Void.
Vyvolaná metoda není podporována v základní třídě. Odvozené třídy musí poskytovat implementaci.
Příklady
Následující příklad používá metodu MakeGenericType k vytvoření vytvořeného typu z definice obecného typu pro Dictionary<TKey,TValue> typ. Vytvořený typ představuje Dictionary<TKey,TValue>Test objekty s řetězcovými klíči.
using System;
using System.Reflection;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
Console.WriteLine("\r\n--- Create a constructed type from the generic Dictionary type.");
// Create a type object representing the generic Dictionary
// type, by omitting the type arguments (but keeping the
// comma that separates them, so the compiler can infer the
// number of type parameters).
Type generic = typeof(Dictionary<,>);
DisplayTypeInfo(generic);
// Create an array of types to substitute for the type
// parameters of Dictionary. The key is of type string, and
// the type to be contained in the Dictionary is Test.
Type[] typeArgs = { typeof(string), typeof(Test) };
// Create a Type object representing the constructed generic
// type.
Type constructed = generic.MakeGenericType(typeArgs);
DisplayTypeInfo(constructed);
// Compare the type objects obtained above to type objects
// obtained using typeof() and GetGenericTypeDefinition().
Console.WriteLine("\r\n--- Compare types obtained by different methods:");
Type t = typeof(Dictionary<String, Test>);
Console.WriteLine("\tAre the constructed types equal? {0}", t == constructed);
Console.WriteLine("\tAre the generic types equal? {0}",
t.GetGenericTypeDefinition() == generic);
}
private static void DisplayTypeInfo(Type t)
{
Console.WriteLine("\r\n{0}", t);
Console.WriteLine("\tIs this a generic type definition? {0}",
t.IsGenericTypeDefinition);
Console.WriteLine("\tIs it a generic type? {0}",
t.IsGenericType);
Type[] typeArguments = t.GetGenericArguments();
Console.WriteLine("\tList type arguments ({0}):", typeArguments.Length);
foreach (Type tParam in typeArguments)
{
Console.WriteLine("\t\t{0}", tParam);
}
}
}
/* This example produces the following output:
--- Create a constructed type from the generic Dictionary type.
System.Collections.Generic.Dictionary`2[TKey,TValue]
Is this a generic type definition? True
Is it a generic type? True
List type arguments (2):
TKey
TValue
System.Collections.Generic.Dictionary`2[System.String, Test]
Is this a generic type definition? False
Is it a generic type? True
List type arguments (2):
System.String
Test
--- Compare types obtained by different methods:
Are the constructed types equal? True
Are the generic types equal? True
*/
open System
open System.Collections.Generic
type Test() = class end
let displayTypeInfo (t: Type) =
printfn $"\r\n{t}"
printfn $"\tIs this a generic type definition? {t.IsGenericTypeDefinition}"
printfn $"\tIs it a generic type? {t.IsGenericType}"
let typeArguments = t.GetGenericArguments()
printfn $"\tList type arguments ({typeArguments.Length}):"
for tParam in typeArguments do
printfn $"\t\t{tParam}"
printfn "\r\n--- Create a constructed type from the generic Dictionary type."
// Create a type object representing the generic Dictionary
// type, by calling .GetGenericTypeDefinition().
let generic = typeof<Dictionary<_,_>>.GetGenericTypeDefinition()
displayTypeInfo generic
// Create an array of types to substitute for the type
// parameters of Dictionary. The key is of type string, and
// the type to be contained in the Dictionary is Test.
let typeArgs = [| typeof<string>; typeof<Test> |]
// Create a Type object representing the constructed generic type.
let constructed = generic.MakeGenericType typeArgs
displayTypeInfo constructed
(* This example produces the following output:
--- Create a constructed type from the generic Dictionary type.
System.Collections.Generic.Dictionary`2[TKey,TValue]
Is this a generic type definition? True
Is it a generic type? True
List type arguments (2):
TKey
TValue
System.Collections.Generic.Dictionary`2[System.String, Test]
Is this a generic type definition? False
Is it a generic type? True
List type arguments (2):
System.String
Test
*)
Public Class Test
Public Shared Sub Main2()
Console.WriteLine(vbCrLf & "--- Create a constructed type from the generic Dictionary type.")
' Create a type object representing the generic Dictionary
' type, by omitting the type arguments (but keeping the
' comma that separates them, so the compiler can infer the
' number of type parameters).
Dim generic As Type = GetType(Dictionary(Of ,))
DisplayTypeInfo(generic)
' Create an array of types to substitute for the type
' parameters of Dictionary. The key is of type string, and
' the type to be contained in the Dictionary is Test.
Dim typeArgs() As Type = {GetType(String), GetType(Test)}
' Create a Type object representing the constructed generic
' type.
Dim constructed As Type = generic.MakeGenericType(typeArgs)
DisplayTypeInfo(constructed)
' Compare the type objects obtained above to type objects
' obtained using GetType() and GetGenericTypeDefinition().
Console.WriteLine(vbCrLf & "--- Compare types obtained by different methods:")
Dim t As Type = GetType(Dictionary(Of String, Test))
Console.WriteLine(vbTab & "Are the constructed types equal? " _
& (t Is constructed))
Console.WriteLine(vbTab & "Are the generic types equal? " _
& (t.GetGenericTypeDefinition() Is generic))
End Sub
Private Shared Sub DisplayTypeInfo(ByVal t As Type)
Console.WriteLine(vbCrLf & t.ToString())
Console.WriteLine(vbTab & "Is this a generic type definition? " _
& t.IsGenericTypeDefinition)
Console.WriteLine(vbTab & "Is it a generic type? " _
& t.IsGenericType)
Dim typeArguments() As Type = t.GetGenericArguments()
Console.WriteLine(vbTab & "List type arguments ({0}):", _
typeArguments.Length)
For Each tParam As Type In typeArguments
Console.WriteLine(vbTab & vbTab & tParam.ToString())
Next
End Sub
End Class
' This example produces the following output:
'
'--- Create a constructed type from the generic Dictionary type.
'
'System.Collections.Generic.Dictionary'2[TKey,TValue]
' Is this a generic type definition? True
' Is it a generic type? True
' List type arguments (2):
' TKey
' TValue
'
'System.Collections.Generic.Dictionary`2[System.String,Test]
' Is this a generic type definition? False
' Is it a generic type? True
' List type arguments (2):
' System.String
' Test
'
'--- Compare types obtained by different methods:
' Are the constructed types equal? True
' Are the generic types equal? True
Poznámky
Tato MakeGenericType metoda umožňuje napsat kód, který přiřazuje konkrétní typy parametrům typu definice obecného typu, a tím vytvořit Type objekt, který představuje konkrétní vytvořený typ. Tento Type objekt můžete použít k vytvoření instancí zkonstruovaného typu v běhovém prostředí.
Typy vytvořené pomocí MakeGenericType mohou být otevřené, to znamená, že některé jejich argumenty typu mohou být parametry typu uzavření obecných metod nebo typů. Takové otevřené konstruované typy můžete použít při generování dynamických sestavení. Představte si například třídy Base a Derived v následujícím kódu.
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
K vygenerování Derived v dynamickém sestavení je nutné vytvořit jeho základní typ. Chcete-li to provést, zavolejte metodu MakeGenericTypeType u objektu představující třídu Base, pomocí argumentů Int32 obecného typu a parametru V typu z Derived. Vzhledem k tomu, že typy i parametry obecného typu jsou reprezentovány Type objekty, lze metodě MakeGenericType předat pole obsahující obojí.
Note
Vytvořený typ, například Base<int, V> je užitečný při generování kódu, ale nelze volat metodu MakeGenericType pro tento typ, protože to není definice obecného typu. Chcete-li vytvořit uzavřený vytvořený typ, který může být instancován, nejprve zavolejte metodu GetGenericTypeDefinition, abyste získali objekt Type představující definici obecného typu, a potom zavolejte MakeGenericType s argumenty požadovaného typu.
Objekt Type vrácený MakeGenericType je stejný jako Type získaný voláním GetType metody výsledného vytvořeného typu nebo GetType metody jakéhokoli vytvořeného typu vytvořeného ze stejné definice obecného typu pomocí stejných argumentů typu.
Note
Pole obecných typů není sám o sobě obecným typem. Není možné zavolat MakeGenericType na typ pole, jako je C<T>[] (Dim ac() As C(Of T) v jazyce Visual Basic). Chcete-li vytvořit uzavřený generický typ z C<T>[], použijte GetElementType k získání definice generického typu C<T>, poté použijte MakeGenericType na tuto definici generického typu k vytvoření konstruovaného typu, a nakonec použijte metodu MakeArrayType na konstruovaný typ k vytvoření typu pole. Totéž platí pro typy ukazatelů a typy ref (ByRef v jazyce Visual Basic).
Seznam invariantních podmínek pro termíny použité v obecné reflexi najdete v IsGenericType poznámkách k vlastnostem.
Vnořené typy
Pokud je obecný typ definován pomocí jazyka C#, C++ nebo Visual Basicu, jsou všechny jeho vnořené typy obecné. To platí i v případě, že vnořené typy nemají vlastní parametry typu, protože všechny tři jazyky obsahují parametry typu ohraničující typy v seznamech parametrů typu vnořených typů. Vezměte v úvahu následující třídy:
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
Seznam typových parametrů vnořené třídy Inner má dva typové parametry, T a U, z nichž první je typovým parametrem její nadřazené třídy. Podobně seznam parametrů typu vnořené třídy Innermost1 má tři parametry typu: T, U, a V, přičemž T a U pocházejí z jejích obalujících tříd. Vnořená třída Innermost2 má dva parametry typu, T a Ukteré pocházejí z jeho uzavřených tříd.
Pokud seznam parametrů ohraničujícího typu obsahuje více než jeden parametr typu, jsou všechny parametry typu v pořadí zahrnuty do seznamu parametrů typu vnořeného typu.
Chcete-li vytvořit obecný typ z definice obecného typu pro vnořený typ, zavolejte MakeGenericType metodu s polem vytvořeným zřetězením pole argumentů typu všech uzavřených typů, počínaje vnějším obecným typem a končící polem argumentů typu samotného vnořeného typu, pokud má vlastní parametry typu. Chcete-li vytvořit instanci Innermost1, zavolejte metodu MakeGenericType s polem obsahujícím tři typy, které mají být přiřazeny K T, U a V. Chcete-li vytvořit instanci Innermost2, volání MakeGenericType metody s polem obsahující dva typy, které mají být přiřazeny K T a U.
Jazyky tímto způsobem šíří parametry typu ohraničující typy, abyste mohli použít parametry typu ohraničujícího typu k definování polí vnořených typů. V opačném případě by parametry typu nebyly v dosahu uvnitř těl vnořených typů. Vnořené typy je možné definovat bez rozšíření parametrů typu ohraničujících typů tak, že vygenerujete kód v dynamických sestaveních nebo pomocí Ilasm.exe (IL Assembler). Představte si následující kód assembleru CIL:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
V tomto příkladu není možné definovat pole typu T nebo U třídy Innermost, protože tyto parametry typu nejsou v oboru. Následující kód assembleru definuje vnořené třídy, které se chovají způsobem, jakým by byly definovány v jazyce C++, Visual Basic a C#:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
Pomocí Ildasm.exe (IL Disassembler) můžete prozkoumat vnořené třídy definované v jazycích vysoké úrovně a sledovat toto schéma pojmenování.