Отражение и универсальные типыReflection and Generic Types

С точки зрения отражения различие между универсальным типом и обычным заключается в том, что с универсальным типом связан набор параметров типа (если это определение универсального типа) или аргументы типа (если это сконструированный тип).From the point of view of reflection, the difference between a generic type and an ordinary type is that a generic type has associated with it a set of type parameters (if it is a generic type definition) or type arguments (if it is a constructed type). Универсальный метод отличается от обычного тем же.A generic method differs from an ordinary method in the same way.

Существует два важных аспекта, необходимых, чтобы понять, как отражение обрабатывает универсальные типы и методы.There are two keys to understanding how reflection handles generic types and methods:

  • Параметры типа определений универсальных типов и определений универсальных методов представлены экземплярами класса Type .The type parameters of generic type definitions and generic method definitions are represented by instances of the Type class.

    Примечание

    Многие свойства и методы класса Type функционируют иначе, если объект Type представляет параметр универсального типа.Many properties and methods of Type have different behavior when a Type object represents a generic type parameter. Эти различия описаны в разделах, посвященных этим свойствам и методам.These differences are documented in the property and method topics. Например, см. класс IsAutoClass и тип DeclaringType.For example, see IsAutoClass and DeclaringType. Кроме того, некоторые элементы действительны, только если объект Type представляет параметр универсального типа.In addition, some members are valid only when a Type object represents a generic type parameter. Пример см. в разделе GetGenericTypeDefinition.For example, see GetGenericTypeDefinition.

  • Если экземпляр типа Type представляет универсальный тип, он содержит массив типов, которые представляют параметры типа (для определений универсального типа) или аргументы типа (для сконструированных типов).If an instance of Type represents a generic type, then it includes an array of types that represent the type parameters (for generic type definitions) or the type arguments (for constructed types). То же самое справедливо для экземпляра класса MethodInfo , который представляет универсальный метод.The same is true of an instance of the MethodInfo class that represents a generic method.

Отражение предоставляет методы Type и MethodInfo, которые позволяют получить доступ к массиву параметров типа и определить, представляет ли экземпляр Type параметр типа или фактический тип.Reflection provides methods of Type and MethodInfo that allow you to access the array of type parameters, and to determine whether an instance of Type represents a type parameter or an actual type.

Пример кода, демонстрирующего описанные здесь методы, см. в статье Руководство. Изучение универсальных типов и создание их экземпляров при помощи отражения.For example code demonstrating the methods discussed here, see How to: Examine and Instantiate Generic Types with Reflection.

В следующем обсуждении предполагается, что вы знакомы с терминологией универсальности, то есть понимаете различия между параметрами типа и аргументами, а также открытыми и закрытыми сконструированными типами.The following discussion assumes familiarity with the terminology of generics, such as the difference between type parameters and arguments and open or closed constructed types. Дополнительные сведения см. в статье Универсальные шаблоны.For more information, see Generics.

Этот обзор состоит из следующих разделов.This overview consists of the following sections:

Это универсальный тип или метод?Is This a Generic Type or Method?

При использовании отражения для изучения неизвестного типа, представленного экземпляром Type, используйте свойство IsGenericType , чтобы определить, является ли неизвестный тип универсальным.When you use reflection to examine an unknown type, represented by an instance of Type, use the IsGenericType property to determine whether the unknown type is generic. Возвращается значение true , если тип является универсальным.It returns true if the type is generic. Аналогично при рассмотрении неизвестного метода, представленного экземпляром класса MethodInfo , воспользуйтесь свойством IsGenericMethod , чтобы установить, является ли метод универсальным.Similarly, when you examine an unknown method, represented by an instance of the MethodInfo class, use the IsGenericMethod property to determine whether the method is generic.

Это определение универсального типа или метода?Is This a Generic Type or Method Definition?

Используйте свойство IsGenericTypeDefinition , чтобы установить, представляет ли объект Type определение универсального типа. Используйте метод IsGenericMethodDefinition , чтобы определить, представляет ли MethodInfo определение универсального метода.Use the IsGenericTypeDefinition property to determine whether a Type object represents a generic type definition, and use the IsGenericMethodDefinition method to determine whether a MethodInfo represents a generic method definition.

Определения универсальных типов и методов — это шаблоны, из которых создаются типы с возможностью создания экземпляров.Generic type and method definitions are the templates from which instantiable types are created. Универсальные типы в библиотеке классов .NET Framework, такие как Dictionary<TKey,TValue>, являются определениями универсальных типов.Generic types in the .NET Framework class library, such as Dictionary<TKey,TValue>, are generic type definitions.

Является ли тип или метод открытым или закрытым?Is the Type or Method Open or Closed?

Универсальный тип или метод является закрытым, если все его параметры типов были заменены типами с возможностью создания экземпляров, включая все параметры всех содержащихся типов.A generic type or method is closed if instantiable types have been substituted for all its type parameters, including all the type parameters of all enclosing types. Создать экземпляр универсального типа можно лишь в том случае, если он закрыт.You can only create an instance of a generic type if it is closed. Свойство Type.ContainsGenericParameters возвращает значение true , если тип открыт.The Type.ContainsGenericParameters property returns true if a type is open. Для методов метод MethodBase.ContainsGenericParameters выполняет ту же функцию.For methods, the MethodBase.ContainsGenericParameters method performs the same function.

К началуBack to top

Создание закрытых универсальных типовGenerating Closed Generic Types

Получив определение универсального типа или метода, воспользуйтесь методом MakeGenericType для создания закрытого универсального типа или методом MakeGenericMethod для создания MethodInfo для закрытого универсального метода.Once you have a generic type or method definition, use the MakeGenericType method to create a closed generic type or the MakeGenericMethod method to create a MethodInfo for a closed generic method.

Получение определения универсального типа или методаGetting the Generic Type or Method Definition

При наличии открытого универсального типа или метода, который не является определением универсального типа или метода, невозможно создать его экземпляры и предоставить отсутствующие параметры типа.If you have an open generic type or method that is not a generic type or method definition, you cannot create instances of it and you cannot supply the type parameters that are missing. Необходимо иметь определение универсального типа или метода.You must have a generic type or method definition. Используйте метод GetGenericTypeDefinition для получения определения универсального типа или метод GetGenericMethodDefinition для получения определения универсального метода.Use the GetGenericTypeDefinition method to obtain the generic type definition or the GetGenericMethodDefinition method to obtain the generic method definition.

Например, если имеется объект Type , представляющий Dictionary<int, string> (Dictionary(Of Integer, String) в Visual Basic) и требуется создать тип Dictionary<string, MyClass>, можно использовать метод GetGenericTypeDefinition для получения объекта Type , который представляет Dictionary<TKey, TValue> , а затем использовать метод MakeGenericType для создания типа Type , который представляет Dictionary<int, MyClass>.For example, if you have a Type object representing Dictionary<int, string> (Dictionary(Of Integer, String) in Visual Basic) and you want to create the type Dictionary<string, MyClass>, you can use the GetGenericTypeDefinition method to get a Type representing Dictionary<TKey, TValue> and then use the MakeGenericType method to produce a Type representing Dictionary<int, MyClass>.

Пример открытого универсального типа, который не является универсальным типом, см. в подразделе «Параметр типа и аргумент типа» далее в этом разделе.For an example of an open generic type that is not a generic type, see "Type Parameter or Type Argument" later in this topic.

К началуBack to top

Изучение аргументов типа и параметров типаExamining Type Arguments and Type Parameters

Используйте метод Type.GetGenericArguments , чтобы получить массив объектов Type , которые представляют параметры типа или аргументы типа для универсального типа; используйте метод MethodInfo.GetGenericArguments , чтобы выполнить то же самое для универсального метода.Use the Type.GetGenericArguments method to obtain an array of Type objects that represent the type parameters or type arguments of a generic type, and use the MethodInfo.GetGenericArguments method to do the same for a generic method.

Если известно, что объект Type представляет параметр типа, отражение может ответить на множество дополнительных вопросов.Once you know that a Type object represents a type parameter, there are many additional questions reflection can answer. Можно определить источник параметра типа, его местоположение и ограничения.You can determine the type parameter's source, its position, and its constraints.

Параметр типа и аргумент типаType Parameter or Type Argument

Чтобы определить, является ли конкретный элемент массива параметром типа или аргументом типа, используйте свойство IsGenericParameter .To determine whether a particular element of the array is a type parameter or a type argument, use the IsGenericParameter property. Свойство IsGenericParameter имеет значение true , если элемент является параметром типа.The IsGenericParameter property is true if the element is a type parameter.

Универсальный тип может быть открытым, не являясь определением универсального типа. В этом случае он содержит как аргументы типа, так и параметры типа.A generic type can be open without being a generic type definition, in which case it has a mixture of type arguments and type parameters. Например, в следующем коде класс D является производным от типа, созданного путем замены первого параметра типа класса D вторым параметром типа B.For example, in the following code, class D derives from a type created by substituting the first type parameter of D for the second type parameter of B.

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> {};  

При получении объекта Type , представляющего D<V, W> , воспользуйтесь свойством BaseType , чтобы получить его базовый тип. Полученный тип type B<int, V> будет открытым, но не будет являться определением универсального типа.If you obtain a Type object representing D<V, W> and use the BaseType property to obtain its base type, the resulting type B<int, V> is open, but it is not a generic type definition.

Источник универсального параметраSource of a Generic Parameter

Параметр универсального типа может происходить от рассматриваемого типа, вмещающего типа или универсального метода.A generic type parameter might come from the type you are examining, from an enclosing type, or from a generic method. Определить источник параметра универсального типа можно следующим образом.You can determine the source of the generic type parameter as follows:

  • Во-первых, используйте свойство DeclaringMethod , чтобы определить, является ли параметр типа производным от универсального метода.First, use the DeclaringMethod property to determine whether the type parameter comes from a generic method. Если значение свойства не является пустой ссылкой (Nothing в Visual Basic), источник — универсальный метод.If the property value is not a null reference (Nothing in Visual Basic), then the source is a generic method.

  • Если источник не является универсальным методом, используйте свойство DeclaringType , чтобы определить универсальный тип, к которому относится параметр универсального типа.If the source is not a generic method, use the DeclaringType property to determine the generic type the generic type parameter belongs to.

Если параметр типа относится к универсальному методу, свойство DeclaringType возвращает тип, объявивший универсальный метод, что не имеет смысла.If the type parameter belongs to a generic method, the DeclaringType property returns the type that declared the generic method, which is irrelevant.

Положение универсального параметраPosition of a Generic Parameter

В редких случаях бывает необходимо определить положение параметра типа в списке параметров типа его объявляющего класса.In rare situations, it is necessary to determine the position of a type parameter in the type parameter list of its declaring class. Допустим, имеется объект Type , представляющий тип B<int, V> из предыдущего примера.For example, suppose you have a Type object representing the B<int, V> type from the preceding example. Метод GetGenericArguments предоставляет список аргументов типа, и при рассмотрении V можно воспользоваться свойствами DeclaringMethod и DeclaringType , чтобы установить его источник.The GetGenericArguments method gives you a list of type arguments, and when you examine V you can use the DeclaringMethod and DeclaringType properties to discover where it comes from. Затем можно использовать свойство GenericParameterPosition , чтобы определить его положение в списке параметров типа, в котором он был определен.You can then use the GenericParameterPosition property to determine its position in the type parameter list where it was defined. В этом примере V находится в положении 0 (ноль) в списке параметров типа, где он был определен.In this example, V is at position 0 (zero) in the type parameter list where it was defined.

Ограничения базового типа и интерфейсаBase Type and Interface Constraints

Используйте метод GetGenericParameterConstraints для получения ограничений базового типа и ограничений интерфейса параметра типа.Use the GetGenericParameterConstraints method to obtain the base type constraint and interface constraints of a type parameter. Порядок элементов массива не имеет значения.The order of the elements of the array is not significant. Элемент представляет ограничение интерфейса, если является типом интерфейса.An element represents an interface constraint if it is an interface type.

Атрибуты универсального параметраGeneric Parameter Attributes

Свойство GenericParameterAttributes получает значение GenericParameterAttributes , которое указывает на дисперсию (ковариация и контрвариация) и особые ограничения параметра типа.The GenericParameterAttributes property gets a GenericParameterAttributes value that indicates the variance (covariance or contravariance) and the special constraints of a type parameter.

Ковариация и контрвариацияCovariance and Contravariance

Чтобы определить, является ли параметр типа ковариантным или контравариантным, примените маску GenericParameterAttributes.VarianceMask к значению GenericParameterAttributes , возвращаемому свойством GenericParameterAttributes .To determine whether a type parameter is covariant or contravariant, apply the GenericParameterAttributes.VarianceMask mask to the GenericParameterAttributes value that is returned by the GenericParameterAttributes property. Если результатом является GenericParameterAttributes.None, параметр типа является инвариантным.If the result is GenericParameterAttributes.None, the type parameter is invariant. См. раздел Ковариация и контрвариация.See Covariance and Contravariance.

Особые ограниченияSpecial Constraints

Чтобы определить особые ограничения параметра типа, примените маску GenericParameterAttributes.SpecialConstraintMask к значению GenericParameterAttributes , возвращаемому свойством GenericParameterAttributes .To determine the special constraints of a type parameter, apply the GenericParameterAttributes.SpecialConstraintMask mask to the GenericParameterAttributes value that is returned by the GenericParameterAttributes property. Если результатом является GenericParameterAttributes.None, специальные ограничения отсутствуют.If the result is GenericParameterAttributes.None, there are no special constraints. Параметр типа может быть ограничен ссылочным типом, являться типом значения, не допускающим значения NULL, и иметь конструктор по умолчанию.A type parameter can be constrained to be a reference type, to be a non-nullable value type, and to have a default constructor.

К началуBack to top

ИнвариантыInvariants

Таблицу неизменяемых условий для общих терминов отражения универсальных типов см. в разделе Type.IsGenericType.For a table of the invariant conditions for common terms in reflection for generic types, see Type.IsGenericType. Дополнительные термины, связанные с универсальными методами, см. в разделе MethodBase.IsGenericMethod.For additional terms relating to generic methods, see MethodBase.IsGenericMethod.

К началуBack to top

ЗаголовокTitle ОписаниеDescription
Практическое руководство. Изучение универсальных типов и создание их экземпляров при помощи отраженияHow to: Examine and Instantiate Generic Types with Reflection Показано использование свойств и методов Type и MethodInfo для изучения универсальных типов.Shows how to use the properties and methods of Type and MethodInfo to examine generic types.
Универсальные шаблоныGenerics Описана универсальность и поддержка этой технологии в .NET Framework.Describes the generics feature and how it is supported in the .NET Framework.
Практическое руководство. Определение универсального типа с порождаемым отражениемHow to: Define a Generic Type with Reflection Emit Показано использование порождения отражения для создания универсальных типов в динамических сборках.Shows how to use reflection emit to generate generic types in dynamic assemblies.
Просмотр сведений о типахViewing Type Information Описывается класс Type и приводятся примеры кода, иллюстрирующие использование Type с несколькими классами отражения для получения информации о конструкторах, методах, полях, свойствах и событиях.Describes the Type class and provides code examples that illustrate how to use Type with various reflection classes to obtain information about constructors, methods, fields, properties, and events.