我正在经历Asp.Net MVC lesson并了解到,为了获得控制器操作资格的方法,
我对某些泛型有所了解,并在某种程度上使用它们,但是:
答案 0 :(得分:180)
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
}
}
如果您运行此代码段,则会打印出
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>
。
答案 1 :(得分:9)
添加:
Dictionary<string, T>
(或者更确切地说是Dictionary<string,>
)仍然是一种开放式。
示例:
void Foo<T>(Dictionary<string,T> dic) { ... }
答案 2 :(得分:6)
“开放泛型类型”只是一种尚未指定其类型的泛型类型(例如,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>()
- 我们现在将其称为已关闭。
答案 3 :(得分:5)
通用类型有三种。简而言之,在这个(简化的)声明中:
public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
Dictionary<TKey, TValue>
是无界通用类型。
KeyValuePair<TKey, TValue>
是开放构建的泛型类型。它有一些类型参数,但它们已在别处定义(在本例中为Dictionary)。
Dictionary<string, int>
将是已关闭的构建泛型类型。