Что именно является «открытым универсальным типом» в .NET? [Дубликат
-
24-09-2019 - |
Вопрос
Этот вопрос уже имеет ответ здесь:
Я шел через Урок ASP.NET MVC и узнал, что для метода для квалификации в качестве действия для контроллера,
- Не должно иметь «Открытый универсальный тип»
Я несколько разбираюсь и использую их в некоторой степени, но:
- Что такое Открытый универсальный тип в .NET.
- Есть ли такая вещь, как Закрытый универсальный тип?
- Открытый универсальный тип это термин не используется очень часто. Что используется / путают с этим?
Решение
Язык C # определяет открытый тип, который должен быть типом, который является либо аргументом типа, либо в общий тип, определенный с помощью аргументов неизвестного типа:
Все типы могут быть классифицированы как открытые типы, либо закрытые типы. Ан. открытый тип это тип, который включает в себя тип параметров. Более конкретно:
- Параметр типа определяет открытый тип.
- Тип массива - это открытый тип, если и только если его тип элемента является открытым типом.
- А. построенный тип это открытый тип, если и только если один или несколько аргументов его типа открытый тип. Отказ А. построен вложенный тип является открытым типом, если и только если один или несколько аргументов его типа или аргументы типа его содержащего тип (ы) - это открытый тип.
А. Закрытый тип это тип, который не является открытым типом.
Следовательно 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
имущество:
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>
.
Другие советы
Просто добавить:
Dictionary<string, T>
(или точнее Dictionary<string,>
) все еще открытый тип.
Пример:
void Foo<T>(Dictionary<string,T> dic) { ... }
«Открытый универсальный тип» - это просто универсальный тип, который еще не имеет указанного типа (например, CargoCrate<T>
). Это становится «закрытым» после назначения бетонного типа (например, CargoCrate<Widget>
).
Например, скажем, у вас есть что-то подобное:
public class Basket<T> {
T[] basketItems;
}
public class PicnicBlanket<T> {
Basket<T> picnicBasket; // Open type here. We don't know what T is.
}
// Closed type here: T is Food.
public class ParkPicnicBlanket : PicnicBlanket<Food> {
}
Здесь, picnicBasket
Тип открыт: ничего еще не назначено T
. Отказ Когда вы делаете бетонный пикникблакет с определенным типом - например, написав PicnicBlanket<Food> p = new PicnicBlanket<Food>()
- Теперь мы называем это закрыто.
Есть три вида общих типов. Чтобы сделать его коротким, в этой (упрощенном) декларации:
public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
Dictionary<TKey, TValue>
является неограниченный родовой тип.KeyValuePair<TKey, TValue>
в этом случае открытый построенный универсальный тип. Отказ Он имеет несколько типовых параметров, но они уже определены в другом месте (в словаре в этом случае).Dictionary<string, int>
будет А. Закрытый построен родовой тип.