Type.MakeGenericType(Type[]) Metod
Definition
Viktigt
En del information gäller för förhandsversionen av en produkt och kan komma att ändras avsevärt innan produkten blir allmänt tillgänglig. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, avseende informationen som visas här.
Ersätter elementen i en matris med typer för typparametrarna i den aktuella generiska typdefinitionen och returnerar ett Type objekt som representerar den resulterande konstruerade typen.
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
Parametrar
- typeArguments
- Type[]
En matris med typer som ska ersättas med typparametrarna för den aktuella generiska typen.
Returer
En Type som representerar den konstruerade typen som bildas genom att ersätta elementen typeArguments i för typparametrarna för den aktuella generiska typen.
- Attribut
Undantag
Den aktuella typen representerar inte en allmän typdefinition. Det vill: IsGenericTypeDefinition returnerar false.
Antalet element i typeArguments är inte detsamma som antalet typparametrar i den aktuella generiska typdefinitionen.
-eller-
Alla element i typeArguments uppfyller inte de begränsningar som angetts för motsvarande typparameter för den aktuella generiska typen.
-eller-
typeArguments innehåller ett element som är en pekartyp (IsPointer returnerar true), en by-ref-typ (IsByRef returnerar true) eller Void.
Den anropade metoden stöds inte i basklassen. Härledda klasser måste tillhandahålla en implementering.
Exempel
I följande exempel används MakeGenericType metoden för att skapa en konstruerad typ från den generiska typdefinitionen Dictionary<TKey,TValue> för typen. Den konstruerade typen representerar ett Dictionary<TKey,TValue> objekt Test med strängnycklar.
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
Kommentarer
Med MakeGenericType metoden kan du skriva kod som tilldelar specifika typer till typparametrarna för en allmän typdefinition, vilket skapar ett Type objekt som representerar en viss konstruktionstyp. Du kan använda det här Type objektet för att skapa exemplar av typen som du har konstruerat.
Typer som konstruerats med MakeGenericType kan vara öppna, dvs. vissa av deras typargument kan vara typparametrar för omslutande generiska metoder eller typer. Du kan använda sådana öppna konstruktionstyper när du genererar dynamiska sammansättningar. Tänk till exempel på klasserna Base och Derived i följande kod.
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
För att generera Derived i en dynamisk sammansättning är det nödvändigt att konstruera dess bastyp. Det gör du genom att anropa MakeGenericType metoden för ett Type objekt som representerar klassen Base, med hjälp av de allmänna typargumenten Int32 och typparametern V från Derived. Eftersom både typer och generiska typparametrar representeras av Type objekt kan en matris som innehåller båda skickas till MakeGenericType metoden.
Note
En konstruerad typ som Base<int, V> är användbar när du genererar kod, men du kan inte anropa metoden för den MakeGenericType här typen eftersom den inte är en allmän typdefinition. Om du vill skapa en sluten GetGenericTypeDefinition konstruktionstyp som kan instansieras anropar du först metoden för att hämta ett Type objekt som representerar den generiska typdefinitionen och anropar MakeGenericType sedan med önskade typargument.
Objektet Type som returneras av MakeGenericType är detsamma som det Type som erhålls genom att anropa GetType metoden för den resulterande konstruerade typen, eller GetType metoden för någon konstruerad typ som skapades från samma generiska typdefinition med samma typargument.
Note
En matris med generiska typer är inte i sig en allmän typ. Du kan inte anropa MakeGenericType en matristyp som C<T>[] (Dim ac() As C(Of T) i Visual Basic). Anropa C<T>[] för att hämta den generiska typdefinitionen GetElementType; anropa C<T> på den generiska typdefinitionen för att skapa den konstruerade typen; och anropa slutligen metoden MakeGenericType på den konstruerade typen för att skapa en matristyp. Detsamma gäller för pekartyper och ref typer (ByRef i Visual Basic).
En lista över de invarianta villkoren för termer som används i allmän reflektion finns i egenskapskommentarerna IsGenericType .
Kapslade typer
Om en allmän typ definieras med C#, C++ eller Visual Basic är alla kapslade typer generiska. Detta gäller även om de kapslade typerna inte har några egna typparametrar, eftersom alla tre språken innehåller typparametrarna för omslutande typer i typparameterlistorna för kapslade typer. Tänk på följande klasser:
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
Typparameterlistan för den kapslade klassen Inner har två typparametrar och TU, varav den första är typparametern för dess omslutande klass. På samma sätt har typparameterlistan för den kapslade klassen Innermost1 tre typparametrar, T, U, och V, med T och U kommer från dess omslutande klasser. Den kapslade klassen Innermost2 har två typparametrar och TU, som kommer från dess omslutande klasser.
Om parameterlistan för den omslutande typen har fler än en typparameter inkluderas alla typparametrar i ordning i typparameterlistan för den kapslade typen.
Om du vill skapa en generisk typ från den generiska typdefinitionen för en kapslad typ anropar MakeGenericType du metoden med matrisen som bildas genom att sammanfoga typargumentmatriserna för alla omslutande typer, med början med den yttersta generiska typen, och slutar med typargumentmatrisen för den kapslade typen, om den har egna typparametrar. Om du vill skapa en instans av Innermost1anropar MakeGenericType du metoden med en matris som innehåller tre typer, som ska tilldelas till T, U och V. Om du vill skapa en instans av Innermost2anropar MakeGenericType du metoden med en matris som innehåller två typer, som ska tilldelas till T och U.
Språken sprider typparametrarna för omslutande typer på det här sättet så att du kan använda typparametrarna för en omslutande typ för att definiera fält av kapslade typer. Annars skulle typparametrarna inte vara tillgängliga inom definitionerna av de kapslade typerna. Det är möjligt att definiera kapslade typer utan att sprida typparametrarna för omslutande typer, genom att generera kod i dynamiska sammansättningar eller med hjälp av Ilasm.exe (IL Assembler). Överväg följande kod för CIL-monteringen:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
I det här exemplet går det inte att definiera ett fält av typen T eller U i klassen Innermost, eftersom dessa typparametrar inte finns i omfånget. Följande assemblerkod definierar kapslade klasser som beter sig som de skulle om de definierades i C++, Visual Basic och C#:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
Du kan använda Ildasm.exe (IL Disassembler) för att undersöka kapslade klasser som definierats i högnivåspråken och observera det här namngivningsschemat.