.NET中的“open generic type”究竟是什么?

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

  • 它不能有一个“开放的genericstypes”

我对generics有所了解,并在一定程度上使用它们,但是:

  • 什么是.NET中的开放式generics
  • 有这样一个封闭genericstypes的东西吗?
  • 开放genericstypes是一个不经常使用的术语。 什么使用/与它混淆?

C#语言将开放types定义为types参数,或者使用未知types参数定义的genericstypes:

所有types可以分为开放式或封闭式。 开放types是涉及types参数的types。 进一步来说:

  • types参数定义了一个开放types。
  • 数组types是当且仅当其元素types是开放types时才是开放types。
  • 一个构造types是一个开放types当且仅当它的一个或多个types参数是一个开放types构造的嵌套types当且仅当它的一个或多个types参数或者它所包含types的types参数是一个开放types时是一个开放types。

封闭型是一种不是开放型的types。

因此, TList<T>Dictionary<string,T>Dictionary<T,U>都是开放types( TU是types参数),而List<int>Dictionary<string,int>是封闭types。

有一个相关的概念:一个未绑定的genericstypes是一个具有未指定types参数的genericstypes。 非绑定types不能用于typeof()以外的expression式,并且不能实例化或调用其方法。 例如, List<>Dictionary<,>是非绑定types。

澄清开放式和非结合式之间的微妙区别:

 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] 

这是List<int>的CLR名称。 在运行时很明显,types参数是System.Int32 。 这使得List<T>成为一个绑定的开放types。

在运行时,可以使用reflection通过Type.MakeGenericType方法将types参数绑定到非绑定genericstypes的未指定types参数:

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

您可以检查一个types是否是一个未绑定的genericstypes( genericstypes定义 ),您可以使用Type.IsGenericTypeDefinition属性构造genericstypes

 Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False 

要在运行时从构造types中获取未绑定types,可以使用Type.GetGenericTypeDefinition方法 。

 Type listOfInt = typeof(List<int>); Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>) 

请注意,对于genericstypes,您可以具有完全未绑定的types定义或完全绑定的定义。 您不能绑定某些types的参数,而让其他人解除绑定。 例如,你不能有Dictionary<int,>Dictionary<,string>

只需添加:

Dictionary<string, T> (或者更准确地说Dictionary<string,> )仍然是一个开放的types。

例:

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

“开放genericstypes”只是一个尚未指定types的genericstypes(例如CargoCrate<T> )。 一旦具体types被赋值,它就变成“closures”(例如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的types是开放的:没有任何东西被分配给T 当你制作一个特定types的具体PicnicBlanket时 – 例如,通过编写PicnicBlanket<Food> p = new PicnicBlanket<Food>() – 我们现在把它叫做closures

有三种通用types。 简而言之,在这个简化的声明中:

 public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> 
  • Dictionary<TKey, TValue>是一个无限的genericstypes

  • 在这种情况下, KeyValuePair<TKey, TValue>是一个开放构造的genericstypes 。 它有一些types参数,但是它们已经在其他地方定义了(在本例中是在Dictionary中)。

  • Dictionary<string, int>将是一个封闭的构造genericstypes