Ответ 1
Язык С# определяет открытый тип как тип, который либо является аргументом типа, либо общим типом, определенным с неизвестными аргументами типа:
Все типы могут быть классифицированы как открытые типы или закрытые типы. Открытый тип - это тип, который включает параметры типа. Более конкретно:
- Параметр типа определяет открытый тип.
- Тип массива является открытым типом тогда и только тогда, когда его тип элемента является открытым типом.
- Созданный тип является открытым типом тогда и только тогда, когда один или несколько его аргументов типа являются открытым типом. Построенный вложенный тип является открытым типом тогда и только тогда, когда один или несколько его аргументов типа или аргументы типа его содержащего типа (ов) являются открытым типом.
Закрытый тип - это тип, который не является открытым.
Поэтому T
, List<T>
и Dictionary<string,T>
, а Dictionary<T,U>
- все открытые типы (T
и U
являются аргументами типа), тогда как List<int>
и Dictionary<string,int>
являются закрытыми типами.
Существует связанная концепция: несвязанный общий тип - это общий тип с неопределенными аргументами типа. Несвязанный тип не может использоваться в выражениях, отличных от typeof()
, и вы не можете его создать или вызвать его методы. Например, List<>
и Dictionary<,>
являются несвязанными типами.
Чтобы прояснить тонкое различие между открытым типом и несвязанным типом:
class Program {
static void Main() { Test<int>(); }
static void Test<T>() {
Console.WriteLine(typeof(List<T>)); // Print out the type name
}
}
Если вы запустите этот фрагмент, он распечатает
System.Collections.Generic.List`1[System.Int32]
который является именем CLR для List<int>
. Во время выполнения ясно, что аргумент типа System.Int32
. Это делает List<T>
связанным открытым типом.
Во время выполнения вы можете использовать отражение для привязки типов аргументов к параметрам неопределенного типа несвязанных общих типов с помощью метода Type.MakeGenericType
:
Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
Console.WriteLine("Constructed a List<int> type.");
Вы можете проверить, является ли тип несвязанным общим типом (определение общего типа), из которого вы можете построить связанные типы с Type.IsGenericTypeDefinition
property:
Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False
Чтобы получить несвязанный тип из построенного типа во время выполнения, вы можете использовать метод Type.GetGenericTypeDefinition
.
Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
Обратите внимание, что для общего типа вы можете либо иметь полностью несвязанное определение типа, либо полностью связанное определение. Вы не можете связывать некоторые параметры типа и оставлять других несвязанными. Например, вы не можете иметь Dictionary<int,>
или Dictionary<,string>
.