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

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

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

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

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

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

Во время выполнения вы можете использовать отражение, чтобы связать аргументы типа с неопределенными параметрами типа несвязанных универсальных типов с помощью 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>,

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

Просто добавить:

Dictionary<string, T> (или точнее Dictionary<string,>) все еще открытый тип.

Пример:

void Foo<T>(Dictionary<string,T> dic) { ... }

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

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

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

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

Другие вопросы по тегам