.NET中的"开放通用类型"究竟是什么?

Asa*_*sad 114 .net c# generics open-generics

我正在通过Asp.Net MVC课程并了解到,对于一种方法来确定控制器的动作,

  • 它必须没有"开放的通用类型"

我对某些泛型有所了解并在某种程度上使用它们,但是:

  • 什么是.Net中的开放泛型类型.
  • 是否存在封闭的泛型类型
  • 开放泛型类型是一个不经常使用的术语.与它混淆使用的是什么?

Meh*_*ari 189

C#语言将open类型定义为类型参数或使用未知类型参数定义的泛型类型:

所有类型都可以分为开放类型或封闭类型.一个开放式的,涉及类型参数的类型.进一步来说:

  • 类型参数定义开放类型.
  • 当且仅当其元素类型是开放类型时,数组类型才是开放类型.
  • 构造类型是开放型,当且仅当其类型参数中的一个或多个是一个开放型.甲构造嵌套类型是开放型,当且仅当其类型参数或包含它的类型的类型参数中的一个或多个是开放类型.

一个封闭式是一种类型,是不是开放类型.

因此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
   }
}
Run Code Online (Sandbox Code Playgroud)

如果您运行此代码段,它将打印出来

System.Collections.Generic.List`1[System.Int32]
Run Code Online (Sandbox Code Playgroud)

这是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.");
Run Code Online (Sandbox Code Playgroud)

您可以检查类型是否是未绑定的泛型类型(泛型类型定义),您可以使用该Type.IsGenericTypeDefinition属性构造绑定类型:

Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False
Run Code Online (Sandbox Code Playgroud)

要在运行时从构造类型获取未绑定类型,可以使用该Type.GetGenericTypeDefinition方法.

Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
Run Code Online (Sandbox Code Playgroud)

请注意,对于泛型类型,您可以具有完全未绑定的类型定义或完全绑定的定义.您无法绑定某些类型参数并使其他参数保持未绑定状态.例如,你不能拥有Dictionary<int,>Dictionary<,string>.

  • +1精彩信息 - 我今天学到了新东西.我知道List <>是一种通用类型,但现在我知道正确的技术术语. (8认同)
  • 您*可以*通过提供本身是开放泛型类型的类型参数来实际部分关闭泛型类型.然而,这是一个死胡同.该框架没有正式承认这种局部状态,将其视为既不封闭也不开放,因此它不允许您对其进行任何有用的操作. (3认同)
  • 我同意@ChrisAmmerman。例如,您声称我们无法拥有的类型'Dictionary &lt;int,&gt;'或多或少由`typeof(Dictionary &lt;,&gt;)。MakeGenericType(typeof(int),typeof(Dictionary &lt;,&gt;))构造。 GetGenericArguments()[1])`。但是也许您只是想说C#不允许语法`Dictionary &lt;int,&gt;`,所以我们必须像在这里一样手动创建它。 (2认同)

lep*_*pie 9

只是添加:

Dictionary<string, T>(或更确切地说Dictionary<string,>)仍然是开放式的.

例:

void Foo<T>(Dictionary<string,T> dic) { ... }
Run Code Online (Sandbox Code Playgroud)

  • 查了一下规格后,我发现你是对的。我认为“通用类型定义”与规范中的“开放类型”相同,但显然,规范调用类型参数和 `List&lt;T&gt;` 开放类型,而 `List&lt;&gt;` 称为未绑定类型。澄清我的答案。+1 (3认同)

Joh*_*lla 7

"开放泛型类型"只是一种尚未指定其类型的泛型类型(例如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> {
}
Run Code Online (Sandbox Code Playgroud)

这里picnicBasket的类型是开放的:尚未分配任何内容T.当您使用特定类型创建具体类型的PicnicBlanket时(例如,通过编写)PicnicBlanket<Food> p = new PicnicBlanket<Food>(),我们现在将其称为已关闭.


Gor*_*pik 6

通用类型有三种.简而言之,在此(简化)声明中:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
Run Code Online (Sandbox Code Playgroud)
  • Dictionary<TKey, TValue>是一种无界的泛型类型.

  • KeyValuePair<TKey, TValue>在这种情况下,是一个开放构造的通用类型.它有一些类型参数,但它们已在别处定义(在本例中为Dictionary).

  • Dictionary<string, int>将是一个封闭的构造泛型类型.