2010-01-31 60 views
100

我正在经历Asp.Net MVC lesson并了解到,对于一个方法有资格作为控制器的动作,.NET中的“open generic type”究竟是什么?

  • 它不能有“开放式泛型类型”

我明白仿制药有些并利用它们在一定程度上,但:

  • 什么是.NET中开放式泛型类型
  • 是否有这样的事情作为封闭泛型类型
  • Open generic type是一个不经常使用的术语。什么使用/与它混淆?

回答

168

C#语言定义的开放式是一种类型的这两种类型参数或未知类型的参数定义的泛型类型:

所有类型都可归类为开放类型或封闭类型。 开放式是一种涉及类型参数的类型。更具体地说:

  • 类型参数定义了一个开放类型。
  • 当且仅当其元素类型为开放类型时,数组类型才是开放类型。
  • A 构造类型当且仅当其一个或多个类型参数是开放类型是一个开放类型。 A 构造的嵌套类型当且仅当其一个或多个类型参数或其包含类型的类型参数是开放类型时是开放类型。

A 封闭式是一种非开放式的类型。

因此TList<T>,和Dictionary<string,T>,和Dictionary<T,U>都是开放类型(TU是类型参数),而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] 

这是List<int>的CLR名称。在运行时很明显,类型参数是System.Int32。这使得List<T>一个约束开放类型。

在运行时,你可以使用反射来绑定类型参数的未绑定的泛型类型的未指定类型参数与Type.MakeGenericType method

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

可以检查类型是否是绑定的泛型类型(泛型类型定义),从中可以构造绑定类型与Type.IsGenericTypeDefinition property

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

为了获得在运行时构造类型的未绑定类型,可以使用Type.GetGenericTypeDefinition method

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

请注意,对于泛型类型,您可以具有完全未绑定的类型定义或完全绑定的定义。您无法绑定某些类型参数,也不能将其他人绑定。例如,您不能有Dictionary<int,>Dictionary<,string>

+8

+1条信息 - 今天我学到了一些新东西。我知道List <>是一个泛型类型,但现在我知道正确的技术术语。 – IAbstract 2010-01-31 20:34:30

+2

您* *实际上可以通过提供一个本身为开放泛型类型的类型参数来部分关闭泛型类型。但是,这是一个死路一条。该框架没有正式承认这种局部状态,认为它既不封闭也不公开,因此它不允许你做任何有用的事情。 – 2010-03-16 21:34:52

+1

关于开放式和非结合式之间的区别的很好的解释 - 以前不知道! – nawfal 2013-05-14 05:08:04

5

“开放泛型类型”只是一个尚未指定类型的泛型类型(例如,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>() - 我们现在称其为已关闭

8

我想补充:

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

例子:

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

@Mehrdad Afshari:对不起,但你仍然可以得到你所说的半封闭类型... – leppie 2010-01-31 21:08:28

+0

另外,我不知道如何构建(或代表类型),可能是一个有价值的问题。 – leppie 2010-01-31 21:11:48

+0

@Mehrdad Afshari:对我来说看起来很开放,但我也乐于接受建议。 :) – leppie 2010-01-31 21:16:07

4

有三种通用类型。要长话短说,在此(简化)声明:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> 
  • Dictionary<TKey, TValue>无限泛型类型

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

  • Dictionary<string, int>将是封闭构建的通用类型