Что такое открытый универсальный тип в .NET?

Я проходил урок Asp.Net MVC и понял, что, для метода, чтобы квалифицироваться как действие для контроллера,

  • У него не должно быть «открытого универсального типа».

Я немного разбираюсь в дженериках и использую их до некоторой степени, но:

  • Что такое открытый универсальный тип в .Net.
  • Есть ли такая вещь, как закрытый универсальный тип?
  • Открытый универсальный тип - это термин, который используется не очень часто. Что с ним используют / путают?

person Asad    schedule 31.01.2010    source источник


Ответы (4)


Язык 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> связанным открытым типом.

Во время выполнения вы можете использовать отражение для привязки аргументов типа к неопределенным параметрам типа несвязанных универсальных типов с помощью _ 17_ метод:

Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
     Console.WriteLine("Constructed a List<int> type.");

Вы можете проверить, является ли тип несвязанным универсальным типом (определение универсального типа), из которого вы можете создавать связанные типы с помощью _ 19_ свойство:

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>.

person mmx    schedule 31.01.2010
comment
+1 отличная информация - сегодня я узнал что-то новое. Я знал, что List ‹› был общим типом, но теперь я знаю правильный технический термин. - person IAbstract; 31.01.2010
comment
Вы можете фактически частично закрыть универсальный тип, предоставив аргумент типа, который сам является открытым универсальным типом. Однако это тупик. Фреймворк официально не распознает это частичное состояние, считая его ни закрытым, ни открытым, и поэтому не позволяет вам делать с ним что-либо полезное. - person Chris Ammerman; 17.03.2010
comment
отличное объяснение разницы между открытым типом и несвязанным типом - раньше не знал! - person nawfal; 14.05.2013
comment
Я согласен с @ChrisAmmerman. Например, тип Dictionary<int,>, который, как вы утверждаете, у нас не может быть, более или менее сконструирован typeof(Dictionary<,>).MakeGenericType(typeof(int), typeof(Dictionary<,>).GetGenericArguments()[1]). Но, возможно, вы просто хотели сказать, что C # не поддерживает синтаксис Dictionary<int,>, поэтому мы должны создать его вручную, как это сделал я здесь. - person Jeppe Stig Nielsen; 14.09.2013
comment
... И на странице doc для IsGenericType в коде C # раздела Примеры они рассматривают более элегантно тип Base`2[System.String,V], в котором один параметр типа заменяется конкретным типом, а другой - параметром V. - person Jeppe Stig Nielsen; 14.09.2013

Просто добавлю:

Dictionary<string, T> (точнее Dictionary<string,>) по-прежнему открытого типа.

Пример:

void Foo<T>(Dictionary<string,T> dic) { ... }
person leppie    schedule 31.01.2010
comment
Посмотрев спецификацию, я вижу, что вы правы. Я думал, что определение универсального типа - это то же самое, что и открытый тип в спецификации, но, очевидно, спецификация вызывает параметр типа и List<T> открытые типы, а List<> - несвязанный тип. Уточняю свой ответ. +1 - person mmx; 01.02.2010

«Открытый универсальный тип» - это просто универсальный тип, для которого еще не указан тип (например, 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>() - мы теперь называем его закрытым.

person John Feminella    schedule 31.01.2010

Есть три типа универсальных типов. Короче говоря, в этом (упрощенном) объявлении:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
  • Dictionary<TKey, TValue> - это неограниченный универсальный тип.

  • KeyValuePair<TKey, TValue> в данном случае является открытым сконструированным универсальным типом. У него есть некоторые параметры типа, но они уже определены где-то в другом месте (в данном случае в Dictionary).

  • Dictionary<string, int> будет закрытым сконструированным универсальным типом.

person Gorpik    schedule 03.02.2010