Type.MakeGenericType(Type[]) Metodo
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Sostituisce gli elementi di una matrice di tipi per i parametri di tipo della definizione di tipo generico corrente e restituisce un Type oggetto che rappresenta il tipo costruito risultante.
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
Parametri
- typeArguments
- Type[]
Matrice di tipi da sostituire con i parametri di tipo del tipo generico corrente.
Valori restituiti
Oggetto Type che rappresenta il tipo costruito formato sostituendo gli elementi di typeArguments per i parametri di tipo del tipo generico corrente.
- Attributi
Eccezioni
Il tipo corrente non rappresenta una definizione di tipo generico. Ovvero, IsGenericTypeDefinition restituisce false.
Il numero di elementi in typeArguments non corrisponde al numero di parametri di tipo nella definizione del tipo generico corrente.
oppure
Qualsiasi elemento di typeArguments non soddisfa i vincoli specificati per il parametro di tipo corrispondente del tipo generico corrente.
oppure
typeArguments contiene un elemento che è un tipo di puntatore (IsPointer restituisce true), un tipo by-ref (IsByRef restituisce true) o Void.
Il metodo richiamato non è supportato nella classe base. Le classi derivate devono fornire un'implementazione.
Esempio
Nell'esempio seguente viene utilizzato il MakeGenericType metodo per creare un tipo costruito dalla definizione di tipo generico per il Dictionary<TKey,TValue> tipo . Il tipo costruito rappresenta un Dictionary<TKey,TValue> oggetto di Test oggetti con chiavi stringa.
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
Commenti
Il MakeGenericType metodo consente di scrivere codice che assegna tipi specifici ai parametri di tipo di una definizione di tipo generico, creando così un Type oggetto che rappresenta un particolare tipo costruito. È possibile usare questo Type oggetto per creare istanze di runtime del tipo costruito.
I tipi costruiti con MakeGenericType possono essere aperti, ovvero alcuni dei loro argomenti di tipo possono essere parametri di tipo di metodi o tipi generici che li racchiudono. Potresti usare tali tipi costruiti aperti quando emetti assembly dinamici. Si considerino ad esempio le classi Base e Derived nel codice seguente.
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
Per generare Derived in un assembly dinamico, è necessario costruire il tipo base. Per fare ciò, chiamare il metodo MakeGenericType su un oggetto Type che rappresenta la classe Base, usando gli argomenti di tipo generico Int32 e il parametro di tipo V da Derived. Poiché i tipi e i parametri di tipo generico sono entrambi rappresentati da Type oggetti , è possibile passare una matrice contenente entrambi al MakeGenericType metodo .
Note
Un tipo costruito, ad esempio Base<int, V> , è utile durante la creazione di codice, ma non è possibile chiamare il MakeGenericType metodo su questo tipo perché non è una definizione di tipo generico. Per creare un tipo costruito chiuso di cui è possibile creare un'istanza, chiamare prima il GetGenericTypeDefinition metodo per ottenere un Type oggetto che rappresenta la definizione del tipo generico e quindi chiamare MakeGenericType con gli argomenti di tipo desiderati.
L'oggetto Type restituito da MakeGenericType è uguale Type a quello ottenuto chiamando il GetType metodo del tipo costruito risultante o il GetType metodo di qualsiasi tipo costruito creato dalla stessa definizione di tipo generico utilizzando gli stessi argomenti di tipo.
Note
Una matrice di tipi generici non è un tipo generico. Non è possibile chiamare MakeGenericType su un tipo di matrice, ad C<T>[] esempio (Dim ac() As C(Of T) in Visual Basic). Per costruire un tipo generico chiuso da C<T>[], chiamare GetElementType per ottenere la definizione di tipo generico , chiamare C<T> sulla definizione MakeGenericTypedel tipo generico per creare il tipo costruito e infine chiamare il MakeArrayType metodo sul tipo costruito per creare il tipo di matrice. Lo stesso vale per i tipi di ref e i tipi puntatore (ByRef in Visual Basic).
Per un elenco delle condizioni invarianti per i termini usati nella reflection generica, vedere le note sulla proprietà IsGenericType.
Tipi annidati
Se un tipo generico viene definito usando C#, C++o Visual Basic, i relativi tipi annidati sono tutti generici. Questo vale anche se i tipi annidati non hanno parametri di tipo propri, perché tutti e tre i linguaggi includono i parametri di tipo dei tipi racchiusi negli elenchi di parametri di tipo dei tipi annidati. Considerare le classi seguenti:
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
L'elenco di parametri di tipo della classe Inner nidificata ha due parametri di tipo, T e U, il primo dei quali è il parametro di tipo della classe contenitore. Analogamente, l'elenco di parametri di tipo della classe Innermost1 nidificata ha tre parametri di tipo, T, Ue V, con T e U provenienti dalle classi che lo racchiudono. La classe nidificata Innermost2 ha due parametri di tipo, T e U, che provengono dalle classi che le racchiudono.
Se l'elenco dei parametri del tipo contenitore include più di un parametro di tipo, tutti i parametri di tipo vengono inclusi nell'elenco dei parametri di tipo del tipo annidato, seguendo l'ordine originale.
Per costruire un tipo generico dalla definizione di tipo generico per un tipo annidato, chiamare il MakeGenericType metodo con la matrice formata concatenando le matrici di argomenti di tipo di tutti i tipi di inclusione, a partire dal tipo generico più esterno e terminando con la matrice di argomenti di tipo del tipo annidato stesso, se dispone di parametri di tipo propri. Per creare un'istanza di Innermost1, chiamare il MakeGenericType metodo con una matrice contenente tre tipi, da assegnare a T, U e V. Per creare un'istanza di Innermost2, chiamare il MakeGenericType metodo con una matrice contenente due tipi, da assegnare a T e U.
I linguaggi propagano i parametri di tipo dei tipi racchiusi in questo modo in modo da poter usare i parametri di tipo di un tipo di inclusione per definire campi di tipi annidati. In caso contrario, i parametri di tipo non sarebbero visibili nell'ambito all'interno dei corpi dei tipi annidati. È possibile definire tipi annidati senza propagare i parametri di tipo dei tipi di inclusione, creando codice in assembly dinamici o usando il Ilasm.exe (Assembler IL). Si consideri il codice seguente per l'assembler CIL:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
In questo esempio non è possibile definire un campo di tipo T o U nella classe Innermost, perché tali parametri di tipo non sono inclusi nell'ambito. Il codice assembler seguente definisce le classi annidate che si comportano nel modo in cui si comportano se definite in C++, Visual Basic e C#:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
È possibile usare il Ildasm.exe (Disassembler IL) per esaminare le classi annidate definite nei linguaggi di alto livello e osservare questo schema di denominazione.