C# язык определяет открытый тип, чтобы быть типа, что это либо тип аргумента или общий тип, определенный с аргументами неизвестного типа:
Все типы могут быть классифицированы как открытого типа или закрытого типа , открытый тип - тип, который включает параметры типа. А именно:
- Параметр типа определяет открытый тип.
- Тип массива является открытым типом тогда и только тогда, когда его тип элемента является открытым типом.
- A построенный тип является открытым типом тогда и только тогда, когда один или несколько аргументов своего типа являются открытым типом. A построенный вложенный тип является открытым типом тогда и только тогда, когда один или несколько аргументов своего типа или аргументы типа его содержащего типа (ов) являются открытым типом.
A закрытый тип - тип, который не является открытым.
Поэтому 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>
a связан открытый тип.
Во время выполнения, вы можете использовать отражение для связывания аргументов типа к параметрам неопределенного типа несвязанных родовых типов с Type.MakeGenericType
method:
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
method.
Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
Обратите внимание, что для универсального типа вы можете либо иметь полностью несвязанное определение типа, либо полностью связанное определение. Вы не можете связывать некоторые параметры типа и оставлять других несвязанными. Например, вы не можете иметь Dictionary<int,>
или Dictionary<,string>
.
+1 отличная информация - сегодня я узнал что-то новое. Я знал, что List <> является общим типом, но теперь я знаю правильный технический термин. – IAbstract
Вы * можете * фактически частично закрыть общий тип, предоставив аргумент типа, который сам является открытым родовым типом. Однако это тупик. Рамка официально не признает это частичное состояние, рассматривая его как закрытое, так и открытое, и поэтому оно не позволяет вам ничего полезного. –
отличное объяснение различий между открытым типом и несвязанным типом - не знал раньше! – nawfal