Emocje ion i typy ogólne
Z punktu widzenia odbicia różnica między typem ogólnym a zwykłym typem polega na tym, że typ ogólny skojarzył z nim zestaw parametrów typu (jeśli jest to definicja typu ogólnego) lub argumenty typu (jeśli jest to typ skonstruowany). Metoda ogólna różni się od zwykłej metody w taki sam sposób.
Istnieją dwa klucze umożliwiające zrozumienie sposobu obsługi typów ogólnych i metod odbicia:
Parametry typu definicji typów ogólnych i definicji metod ogólnych są reprezentowane przez wystąpienia Type klasy.
Uwaga
Wiele właściwości i metod Type ma inne zachowanie, gdy Type obiekt reprezentuje parametr typu ogólnego. Te różnice są udokumentowane w artykułach dotyczących właściwości i metod. Na przykład zobacz IsAutoClass i DeclaringType. Ponadto niektóre elementy członkowskie są prawidłowe tylko wtedy, gdy Type obiekt reprezentuje parametr typu ogólnego. Na przykład zobacz GetGenericTypeDefinition.
Jeśli wystąpienie Type reprezentuje typ ogólny, zawiera tablicę typów reprezentujących parametry typu (dla definicji typów ogólnych) lub argumenty typu (dla typów skonstruowanych). To samo dotyczy wystąpienia MethodInfo klasy reprezentującej metodę ogólną.
Emocje ion udostępnia metody Type i MethodInfo umożliwiają dostęp do tablicy parametrów typu oraz określenie, czy wystąpienie Type reprezentuje parametr typu, czy rzeczywisty typ.
Na przykład kod demonstrujący omówione tutaj metody można znaleźć w temacie How to: Examine and Instantiate Generic Types with Emocje ion (Instrukcje: badanie i tworzenie wystąpień typów ogólnych za pomocą Emocje ion).
W poniższej dyskusji założono, że znajomość terminologii rodzajowej, takiej jak różnica między parametrami typu i argumentami oraz otwartymi lub zamkniętymi typami skonstruowanymi. Aby uzyskać więcej informacji, zobacz Ogólne.
Czy jest to typ ogólny lub metoda?
Jeśli używasz odbicia do zbadania nieznanego Typetypu, reprezentowanego przez wystąpienie klasy , użyj IsGenericType właściwości , aby określić, czy nieznany typ jest ogólny. Zwraca wartość true
, jeśli typ jest ogólny. Podobnie podczas badania nieznanej metody reprezentowanej przez wystąpienie MethodInfo klasy użyj IsGenericMethod właściwości , aby określić, czy metoda jest ogólna.
Czy jest to typ ogólny lub definicja metody?
IsGenericTypeDefinition Użyj właściwości , aby określić, czy Type obiekt reprezentuje definicję typu ogólnego, i użyj IsGenericMethodDefinition metody , aby określić, czy MethodInfo reprezentuje definicję metody ogólnej.
Definicje typów ogólnych i metod to szablony, z których tworzone są wystąpienia typów. Typy ogólne w bibliotekach platformy .NET, takie jak Dictionary<TKey,TValue>, to definicje typów ogólnych.
Czy typ lub metoda jest otwarta, czy zamknięta?
Typ ogólny lub metoda jest zamknięta, jeśli wystąpienia typów zostały zastąpione dla wszystkich parametrów typu, w tym wszystkich parametrów typu wszystkich ujęć typów. Wystąpienie typu ogólnego można utworzyć tylko wtedy, gdy jest zamknięte. Właściwość Type.ContainsGenericParameters zwraca true
wartość , jeśli typ jest otwarty. W przypadku metod MethodBase.ContainsGenericParameters metoda wykonuje tę samą funkcję.
Generowanie zamkniętych typów ogólnych
Gdy masz definicję typu ogólnego lub metody, użyj MakeGenericType metody , aby utworzyć zamknięty typ ogólny lub MakeGenericMethod metodę , aby utworzyć MethodInfo metodę dla zamkniętej metody ogólnej.
Pobieranie definicji typu ogólnego lub metody
Jeśli masz otwarty typ ogólny lub metodę, która nie jest typem ogólnym lub definicją metody, nie możesz utworzyć wystąpień i nie możesz podać brakujących parametrów typu. Musisz mieć definicję typu ogólnego lub metody. GetGenericTypeDefinition Użyj metody , aby uzyskać definicję typu ogólnego lub GetGenericMethodDefinition metodę w celu uzyskania definicji metody ogólnej.
Jeśli na przykład masz obiekt reprezentujący Dictionary<int, string>
i chcesz utworzyć typ Dictionary<string, MyClass>
, możesz użyć GetGenericTypeDefinition metody , aby uzyskać reprezentację TypeDictionary<TKey, TValue>
, a następnie użyć MakeGenericType metody , aby utworzyć reprezentację TypeDictionary<int, MyClass>
.Type
Aby zapoznać się z przykładem otwartego typu ogólnego, który nie jest typem ogólnym, zobacz Typ parametru lub argumentu typu.
Badanie argumentów typu i parametrów typu
Type.GetGenericArguments Użyj metody , aby uzyskać tablicę Type obiektów, które reprezentują parametry typu lub argumenty typu typu, i użyj MethodInfo.GetGenericArguments metody , aby wykonać to samo dla metody ogólnej.
Gdy już wiesz, że Type obiekt reprezentuje parametr typu, istnieje wiele dodatkowych pytań, na które można odpowiedzieć. Możesz określić źródło parametru typu, jego położenie i ograniczenia.
Typ parametru lub argumentu typu
Aby określić, czy określony element tablicy jest parametrem typu, czy argumentem typu, użyj IsGenericParameter właściwości . Właściwość IsGenericParameter ma true
wartość , jeśli element jest parametrem typu.
Typ ogólny może być otwarty bez bycia definicją typu ogólnego, w którym przypadku ma kombinację argumentów typu i parametrów typu. Na przykład w poniższym kodzie klasa D
pochodzi z typu utworzonego przez podstawianie pierwszego parametru D
typu dla drugiego parametru B
typu .
class B<T, U> {}
class D<V, W> : B<int, V> {}
Class B(Of T, U)
End Class
Class D(Of V, W)
Inherits B(Of Integer, V)
End Class
generic<typename T, typename U> ref class B {};
generic<typename V, typename W> ref class D : B<int, V> {};
Jeśli uzyskasz Type obiekt reprezentujący D<V, W>
i użyjesz BaseType właściwości , aby uzyskać jej typ podstawowy, wynik type B<int, V>
jest otwarty, ale nie jest to definicja typu ogólnego.
Źródło parametru ogólnego
Ogólny parametr typu może pochodzić z sprawdzanego typu, od otaczającego typu lub z metody ogólnej. Źródło parametru typu ogólnego można określić w następujący sposób:
- Najpierw użyj DeclaringMethod właściwości , aby określić, czy parametr typu pochodzi z metody ogólnej. Jeśli wartość właściwości nie jest odwołaniem o wartości null, źródło jest metodą ogólną.
- Jeśli źródło nie jest metodą ogólną, użyj DeclaringType właściwości , aby określić typ ogólny, do którego należy parametr typu ogólnego.
Jeśli parametr typu należy do metody ogólnej, DeclaringType właściwość zwraca typ, który zadeklarował metodę ogólną, co jest nieistotne.
Położenie parametru ogólnego
W rzadkich sytuacjach konieczne jest określenie pozycji parametru typu na liście parametrów typu jego klasy deklaratywnej. Załóżmy na przykład, że masz Type obiekt reprezentujący B<int, V>
typ z poprzedniego przykładu. Metoda GetGenericArguments udostępnia listę argumentów typu, a podczas badania V
możesz użyć DeclaringMethod właściwości i DeclaringType , aby dowiedzieć się, skąd pochodzi. Następnie możesz użyć GenericParameterPosition właściwości , aby określić jej pozycję na liście parametrów typu, w której została zdefiniowana. W tym przykładzie V
znajduje się na pozycji 0 (zero) na liście parametrów typu, gdzie została zdefiniowana.
Ograniczenia typu podstawowego i interfejsu
GetGenericParameterConstraints Użyj metody , aby uzyskać ograniczenie typu podstawowego i ograniczenia interfejsu parametru typu. Kolejność elementów tablicy nie jest znacząca. Element reprezentuje ograniczenie interfejsu, jeśli jest to typ interfejsu.
Atrybuty parametrów ogólnych
Właściwość GenericParameterAttributes pobiera GenericParameterAttributes wartość, która wskazuje wariancję (kowariancję lub kontrawariancję) oraz specjalne ograniczenia parametru typu.
Kowariancja i kontrawariancja
Aby określić, czy parametr typu jest kowariantny, czy kontrawariantny, zastosuj maskę GenericParameterAttributes.VarianceMask do GenericParameterAttributes wartości zwracanej przez GenericParameterAttributes właściwość. Jeśli wynik to GenericParameterAttributes.None, parametr typu jest niezmienny. Aby uzyskać więcej informacji, zobacz Covariance i Contravariance.
Ograniczenia specjalne
Aby określić specjalne ograniczenia parametru typu, zastosuj maskę GenericParameterAttributes.SpecialConstraintMask do GenericParameterAttributes wartości zwracanej przez GenericParameterAttributes właściwość . Jeśli wynikiem jest GenericParameterAttributes.None, nie ma specjalnych ograniczeń. Parametr typu może być ograniczony jako typ odwołania, jako typ niezwiązany z wartością null i mieć konstruktor bez parametrów.
Invariants
Aby uzyskać tabelę niezmiennych warunków dla typowych terminów odbicia dla typów ogólnych, zobacz Type.IsGenericType. Aby uzyskać dodatkowe terminy dotyczące metod ogólnych, zobacz MethodBase.IsGenericMethod.