.NET泛型术语有些含糊不清。更糟糕的是,在不同的来源中,它似乎被使用得含糊和不同。基本上不清楚的是这4个术语与“Type”之间的关系:
- 开放的
- 封闭的
- 未绑定的
- 已构建的
我了解到List<T>
是开放的,List<int>
是封闭的。但是在开放/封闭类型方面,“已构建的”和“未绑定的”到底是什么呢?
从语言规范中获取:
4.4 构造类型
仅有泛型类型声明本身表示未绑定的泛型类型,通过应用类型参数,可以使用它作为生成许多不同类型的“蓝图”。类型参数写在尖括号(<和>)内,紧随泛型类型名称之后。包含至少一个类型参数的类型称为构造类型。几乎在语言的任何地方都可以使用构造类型,只要可以使用类型名称的地方即可。未绑定的泛型类型只能在typeof表达式(§7.6.11)中使用。
4.4.2 开放类型和封闭类型
所有类型都可以归类为开放类型或封闭类型。开放类型是涉及类型参数的类型。更具体地说:
• 类型参数定义开放类型。
• 仅当其元素类型为开放类型时,数组类型才是开放类型。
• 构造类型是开放类型,仅当其一个或多个类型参数为开放类型时。嵌套的构造类型是开放类型,仅当其一个或多个类型参数或其包含类型的类型参数为开放类型时。
封闭类型不是开放类型。
4.4.3 绑定类型和未绑定类型
术语未绑定类型指非泛型类型或未绑定的泛型类型。术语绑定类型指非泛型类型或构造类型。未绑定类型是由类型声明声明的实体。未绑定的泛型类型本身不是类型,并且不能用作变量、参数或返回值的类型,也不能用作基础类型。未绑定的泛型类型可以被引用的唯一构造形式是typeof表达式(§7.6.11)。
这里有一个我想到的例子:
// Foo<T> is an unbound generic type.
class Foo<T> { .. }
// Bar<K> is an unbound generic type.
// Its base-class Foo<K> is a constructed, open generic type.
class Bar<K> : Foo<K> { .. }
// IntFoo is not a generic type.
// Its base-class Foo<int> is a constructed, closed generic type.
class IntFoo : Foo<int> { .. }
以下是使用反射API和相关属性尝试将其与之联系起来的方法:IsGenericType
、IsGenericTypeDefinition
和ContainsGenericParameters
(这些测试并不能完全预测每种类型,因为它们与语言规范不完全相符。)
+----------+---------------------+-----------+--------------+-------------------+
| Name | Kind | IsGenType | IsGenTypeDef | ContainsGenParams |
+----------+---------------------+-----------+--------------+-------------------+
| Foo<> | Unbound | TRUE | TRUE | TRUE |
| Foo<>* | Constructed, open | TRUE | FALSE | TRUE |
| Foo<int> | Constructed, closed | TRUE | FALSE | FALSE |
| IntFoo | Not generic | FALSE | FALSE | FALSE |
+----------+---------------------+-----------+--------------+-------------------+
* = Bar<>'s base type.
IsGenericType
的文档页面示例。有关新属性IsConstructedGenericType
,请参见我刚刚发布的讨论帖子。 - Jeppe Stig Nielsen