Condividi tramite


Metodo System.Type.MakeGenericType

Questo articolo fornisce osservazioni supplementari alla documentazione di riferimento per questa API.

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 relativi argomenti di tipo possono essere parametri di tipo di contenitore di metodi o tipi generici. È possibile usare tali tipi costruiti aperti quando si generano 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 di base. A tale scopo, chiamare il MakeGenericType metodo su un Type oggetto che rappresenta la classe Base, usando gli argomenti di tipo generico Int32 e il parametro V di tipo 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 .

Nota

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.

Nota

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 MakeGenericType sulla definizione C<T>del 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 e ref i tipi puntatore (ByRef in Visual Basic).

Per un elenco delle condizioni invariabili relative ai termini usati dal processo di reflection generico, vedere i commenti 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 T di tipo e U, il primo dei quali è il parametro di tipo della relativa 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 Innermost2 nidificata ha due parametri di tipo e UT , che provengono dalle classi che lo racchiudono.

Se l'elenco di parametri del tipo di inclusione ha più di un parametro di tipo, tutti i parametri di tipo in ordine vengono inclusi nell'elenco dei parametri di tipo del tipo annidato.

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 si trovano 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 l'assembler IL (Ilasm.exe). 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.