Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
С точки зрения отражения разница между универсальным типом и обычным типом заключается в том, что универсальный тип связан с ним набором параметров типа (если это определение универсального типа) или аргументы типа (если это созданный тип). Универсальный метод отличается от обычного метода таким же образом.
Существует два ключа для понимания того, как отражение обрабатывает универсальные типы и методы:
Параметры типа определений универсальных типов и определений универсальных методов представлены экземплярами Type класса.
Замечание
Многие свойства и методы имеют другое поведение, если Type объект представляет параметр универсального Type типа. Эти различия описаны в статьях свойств и методов. Например, см IsAutoClass . и DeclaringType. Кроме того, некоторые члены допустимы только в том случае, если Type объект представляет параметр универсального типа. Например, ознакомьтесь со статьей GetGenericTypeDefinition.
Если экземпляр Type представляет универсальный тип, он включает массив типов, представляющих параметры типа (для определений универсальных типов) или аргументы типа (для созданных типов). То же самое относится к экземпляру MethodInfo класса, представляющего универсальный метод.
Отражение предоставляет методы Type и MethodInfo позволяет получить доступ к массиву параметров типа и определить, представляет ли экземпляр Type параметр типа или фактический тип.
Пример кода, демонстрирующий методы, рассмотренные здесь, см. в разделе "Практическое руководство. Изучение и создание экземпляров универсальных типов с отражением".
В следующем обсуждении предполагается знакомство с терминологией универсальных шаблонов, например различие между параметрами типа и аргументами и открытыми или закрытыми созданными типами. Дополнительные сведения см. в разделе «Обобщения».
Это универсальный тип или метод?
При использовании отражения для изучения неизвестного типа, представленного экземпляром Type, используйте IsGenericType свойство, чтобы определить, является ли неизвестный тип универсальным. Возвращается true
, если тип является универсальным. Аналогичным образом при проверке неизвестного MethodInfo метода, представленного экземпляром класса, используйте IsGenericMethod свойство, чтобы определить, является ли метод универсальным.
Это определение универсального типа или метода?
IsGenericTypeDefinition Используйте свойство, чтобы определить, представляет ли Type объект определение универсального типа, и используйте IsGenericMethodDefinition метод, чтобы определить, представляет ли MethodInfo определение универсального метода.
Определения универсальных типов и методов — это шаблоны, из которых создаются экземплярные типы. Универсальные типы в библиотеках .NET, например Dictionary<TKey,TValue>, являются определениями универсальных типов.
Открыт или закрыт ли тип или метод?
Универсальный тип или метод закрывается, если экземпляры были заменены всеми параметрами типа, включая все параметры типа всех вложенных типов. Экземпляр универсального типа можно создать только в том случае, если он закрыт. Свойство возвращаетсяType.ContainsGenericParameters, true
если тип открыт. Для методов MethodBase.ContainsGenericParameters метод выполняет ту же функцию.
Создание закрытых универсальных типов
После создания универсального типа или определения метода используйте MakeGenericType метод для создания закрытого универсального типа или MakeGenericMethod метода для создания MethodInfo закрытого универсального метода.
Получение определения универсального типа или метода
Если у вас есть открытый универсальный тип или метод, который не является универсальным типом или определением метода, невозможно создать экземпляры этого типа и указать отсутствующие параметры типа. У вас должен быть универсальный тип или определение метода. GetGenericTypeDefinition Используйте метод для получения определения универсального типа или GetGenericMethodDefinition метода для получения определения универсального метода.
Например, если у вас есть Type объект, представляющий Dictionary<int, string>
и вы хотите создать тип Dictionary<string, MyClass>
, можно использовать GetGenericTypeDefinition метод для получения Type представления Dictionary<TKey, TValue>
, а затем использовать MakeGenericType метод для создания Type представления Dictionary<int, MyClass>
.
Пример открытого универсального типа, который не является универсальным типом, см. в разделе "Параметр типа" или аргумент типа.
Проверка аргументов типа и параметров типа
Type.GetGenericArguments Используйте метод для получения массива Type объектов, представляющих параметры типа или аргументы типа универсального типа, и используйте MethodInfo.GetGenericArguments этот метод, чтобы сделать то же самое для универсального метода.
После того как вы знаете, что Type объект представляет параметр типа, есть много дополнительных вопросов, которые могут ответить. Вы можете определить источник параметра типа, его положение и ограничения.
Аргумент типа или аргумент типа
Чтобы определить, является ли определенный элемент массива параметром типа или аргументом типа, используйте IsGenericParameter это свойство. Свойство IsGenericParameter имеет значение true
, если элемент является параметром типа.
Универсальный тип может быть открыт без определения универсального типа, в этом случае он имеет смесь аргументов типа и параметров типа. Например, в следующем коде класс D
является производным от типа, созданного путем замены первого параметра D
типа для второго параметра 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
Если вы получите Type объект, представляющий D<V, W>
и используйте BaseType свойство для получения базового типа, результат type B<int, V>
открыт, но это не определение универсального типа.
Источник универсального параметра
Параметр универсального типа может быть получен из проверяемого типа, от включающего типа или из универсального метода. Вы можете определить источник параметра универсального типа следующим образом:
- Во-первых, используйте DeclaringMethod свойство, чтобы определить, исходит ли параметр типа из универсального метода. Если значение свойства не является пустой ссылкой, источник является универсальным методом.
- Если источник не является универсальным методом, используйте DeclaringType свойство для определения универсального типа, к которому принадлежит параметр универсального типа.
Если параметр типа принадлежит универсальному методу, DeclaringType свойство возвращает тип, объявленный универсальным методом, который не имеет значения.
Позиция универсального параметра
В редких ситуациях необходимо определить положение параметра типа в списке параметров типа его декларативного класса. Например, предположим, что у вас есть Type объект, B<int, V>
представляющий тип из предыдущего примера. Этот GetGenericArguments метод предоставляет список аргументов типа, а при проверке V
можно использовать DeclaringMethod свойства и DeclaringType определить, откуда он поступает. Затем можно использовать GenericParameterPosition свойство, чтобы определить его положение в списке параметров типа, где он был определен. В этом примере V
находится на позиции 0 (ноль) в списке параметров типа, где он был определен.
Ограничения базового типа и интерфейса
GetGenericParameterConstraints Используйте метод для получения ограничений базового типа и ограничений интерфейса параметра типа. Порядок элементов массива не является значительным. Элемент представляет ограничение интерфейса, если это тип интерфейса.
Атрибуты универсальных параметров
Свойство GenericParameterAttributes получает GenericParameterAttributes значение, указывающее дисперсию (ковариацию или контравариацию) и специальные ограничения параметра типа.
Ковариантность и контрвариантность
Чтобы определить, является ли параметр типа ковариантным или контравариантным, примените маску GenericParameterAttributes.VarianceMask к GenericParameterAttributes значению, возвращаемого свойством GenericParameterAttributes . Если результат имеет значение GenericParameterAttributes.None, параметр типа является инвариантным. Дополнительные сведения см. в разделе Ковариантность и контравариантность.
Специальные ограничения
Чтобы определить специальные ограничения параметра типа, примените маску GenericParameterAttributes.SpecialConstraintMask к GenericParameterAttributes значению, возвращаемого свойством GenericParameterAttributes . Если результат имеется GenericParameterAttributes.None, нет специальных ограничений. Параметр типа может быть ссылочным типом, не допускаемым значением NULL, а также иметь конструктор без параметров.
Инварианты
Таблица инвариантных условий для распространенных терминов в отражении универсальных типов см. в разделе Type.IsGenericType. Дополнительные термины, относящиеся к универсальным методам, см. в разделе MethodBase.IsGenericMethod.