System.Type.MakeGenericType, metoda
Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.
Metoda MakeGenericType umożliwia pisanie kodu, który przypisuje określone typy do parametrów typu definicji typu ogólnego, tworząc w ten sposób Type obiekt reprezentujący określony typ skonstruowany. Tego obiektu można użyć Type do utworzenia wystąpień czasu wykonywania skonstruowanego typu.
Typy skonstruowane za pomocą MakeGenericType mogą być otwarte, czyli niektóre z ich argumentów typu mogą być parametrami typu otaczającej metody ogólne lub typy. Podczas emitowanych zestawów dynamicznych można użyć takich otwartych typów skonstruowanych. Rozważmy na przykład klasy Base
i Derived
w poniższym kodzie.
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
Aby wygenerować Derived
w zestawie dynamicznym, należy skonstruować jego typ podstawowy. W tym celu wywołaj metodę MakeGenericType dla obiektu reprezentującego klasę Base
Type , używając argumentów Int32 typu ogólnego i parametru V
typu z klasy Derived
. Ponieważ typy i parametry typu ogólnego są reprezentowane przez Type obiekty, tablica zawierająca oba można przekazać do MakeGenericType metody .
Uwaga
Skonstruowany typ, taki jak Base<int, V>
jest przydatny podczas emitowania kodu, ale nie można wywołać MakeGenericType metody dla tego typu, ponieważ nie jest to definicja typu ogólnego. Aby utworzyć zamknięty skonstruowany typ, który można utworzyć, najpierw wywołaj GetGenericTypeDefinition metodę , aby uzyskać obiekt reprezentujący definicję Type typu ogólnego, a następnie wywołać MakeGenericType z żądanymi argumentami typu.
Type Obiekt zwracany MakeGenericType przez element jest taki sam jak Type uzyskany przez wywołanie GetType metody wynikowego typu skonstruowanego lub GetType metody dowolnego skonstruowanego typu utworzonego na podstawie tej samej definicji typu ogólnego przy użyciu argumentów tego samego typu.
Uwaga
Tablica typów ogólnych nie jest typem ogólnym. Nie można wywołać MakeGenericType typu tablicy, takiego jak C<T>[]
(Dim ac() As C(Of T)
w Visual Basic). Aby skonstruować zamknięty typ ogólny z C<T>[]
klasy , wywołaj GetElementType metodę w celu uzyskania ogólnej definicji C<T>
typu ; wywołaj MakeGenericType definicję typu ogólnego w celu utworzenia skonstruowanego typu, a na koniec wywołaj MakeArrayType metodę na skonstruowanym typie, aby utworzyć typ tablicy. To samo dotyczy typów i ref
typów wskaźników (ByRef
w Visual Basic).
Aby zapoznać się z listą niezmiennych warunków warunków używanych w odbiciu ogólnym, zobacz IsGenericType uwagi dotyczące właściwości.
Zagnieżdżone typy
Jeśli typ ogólny jest zdefiniowany przy użyciu języka C#, C++lub Visual Basic, wszystkie typy zagnieżdżone są ogólne. Jest to prawdą, nawet jeśli zagnieżdżone typy nie mają własnych parametrów typu, ponieważ wszystkie trzy języki zawierają parametry typu otaczające typy na listach parametrów typu zagnieżdżonych typów. Rozważ następujące klasy:
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
Lista parametrów typu klasy Inner
zagnieżdżonej ma dwa parametry typu, T
a U
pierwszy z nich jest parametrem typu klasy otaczającej. Podobnie lista parametrów typu zagnieżdżonej klasy Innermost1
ma trzy parametry typu, T
, U
i V
, z elementami i U
pochodzącymi z T
jej klas otaczających. Zagnieżdżona klasa Innermost2
ma dwa parametry typu i T
U
, które pochodzą z ujęć klas.
Jeśli lista parametrów typu otaczającego ma więcej niż jeden parametr typu, wszystkie parametry typu w kolejności są uwzględnione na liście parametrów typu typu typu.
Aby utworzyć typ ogólny z ogólnej definicji typu dla typu zagnieżdżonego, wywołaj MakeGenericType metodę z tablicą utworzoną przez łączenie tablic argumentów typu wszystkich ujęć typów, począwszy od najbardziej zewnętrznego typu ogólnego, a kończąc na tablicy argumentów typu samego typu zagnieżdżonego, jeśli ma własne parametry typu. Aby utworzyć wystąpienie Innermost1
klasy , wywołaj MakeGenericType metodę za pomocą tablicy zawierającej trzy typy, które mają być przypisane do klas T, U i V. Aby utworzyć wystąpienie Innermost2
klasy , wywołaj MakeGenericType metodę z tablicą zawierającą dwa typy, które mają być przypisane do języka T i U.
Języki propagują parametry typu otaczającego typów w ten sposób, aby można było użyć parametrów typu otaczającego typu do zdefiniowania pól typów zagnieżdżonych. W przeciwnym razie parametry typu nie będą znajdować się w zakresie w obrębie treści zagnieżdżonych typów. Istnieje możliwość definiowania typów zagnieżdżonych bez propagacji parametrów typu ujęć typów, emitując kod w zestawach dynamicznych lub używając Ilasm.exe (asemblera IL). Rozważ następujący kod dla asemblera CIL:
.class public Outer<T> {
.class nested public Inner<U> {
.class nested public Innermost {
}
}
}
W tym przykładzie nie można zdefiniować pola typu T
lub U
klasy Innermost
, ponieważ te parametry typu nie znajdują się w zakresie. Poniższy kod asemblera definiuje zagnieżdżone klasy, które zachowują się tak, jakby były zdefiniowane w językach C++, Visual Basic i C#:
.class public Outer<T> {
.class nested public Inner<T, U> {
.class nested public Innermost<T, U, V> {
}
}
}
Za pomocą Ildasm.exe (dezasembler IL) można sprawdzić klasy zagnieżdżone zdefiniowane w językach wysokiego poziomu i obserwować ten schemat nazewnictwa.