接泛型二
20.4 泛型委託聲明
委託聲明可以包含型別參數。
delegate-declaration:
attributes opt delegate-modifiers op t delegate return-type identifier type-parameter-list opt
(formal-parameter-list opt) type-parameter-list opt
(formal-parameter-list opt) type-parameter-conintonestype-opt 聲明)選委託修飾符可選delegate 傳回類型識別符類型參數清單可選(正式參數清單可選)類型參數約束語句可選
使用類型參數聲明的委託是一個泛型委託聲明。清單時,才能支援類型參數約束語句(§20.7)。的特定聲明空間(§3.3)定義了一個名字。實參以形成構造委託類型。構造委託類型相容。在§21.9中有說明。 。可以出現的大多數地方。當名字被計算時,只有帶有正確數量類型參數的泛型類型會被考慮。可能的。對於模糊性的決議在§20.6.5中進行了描述。
類型名字可能標識一個建構類型,儘管它沒有直接指定類型參數。這種情況在一個類型嵌套在一個泛型類別聲明中時就會出現,並且包含聲明的實例類型將因為名字查找(§20.1.2)而被隱式地使用。
delegate bool Predicate<T>(T value) class X { static bool F(int i){…} static bool G(string s){…} static void Main(){ Predicate<int> p1 = F; Predicate<string> p2=G; } }
在不安全程式碼中,建構型別不能被用作非託管型別(§18.2)。
在一個類型參數列表中的每個實參都只是一個類型。
static void Main(){ Predicate<int> p1 = new Predicate<int>(F); Predicate<string> p2 = new Predicate<string>(G); }
型實參反過來也可以是構造型別或型別參數。在不安全代碼中(§18),類型實參不能是指標類型。每個類型實參必須遵循對應類型參數(§20.7.1)上的任何約束。
20.5.2开放和封闭类型
所有类型都可以被分为开放类型(open type)或封闭类型(closed type)。开放类型是包含类型参数的类型。更明确的说法是
类型参数定义了一个开放类型
数组类型只有当其元素是一个开放类型时才是开放类型
构造类型只有当其类型实参中的一个或多个是开放类型时,它才是开放类型
非开放类型都是封闭类型。
在运行时,在泛型类型声明中的所有代码都在一个封闭构造类型的上下文执行,这个封闭构造类型是通过将类型实参应用到泛型声明中创建的。在泛型类型中的每个类型实参被绑定到一个特定运行时类型。所有语句和表达式的运行时处理总是针对封闭类型发生,而开放类型只发生在编译时处理。
每个封闭构造类型都有它自己的一组静态变量,它们并不被其他封闭类型共享。因为在运行时不存在开放类型,所以开放类型没有关联的静态变量。如果两个封闭构造类型是从同一个类型声明构造的,并且对应的类型实参也是相同的类型,那么它们就是相同的类型。
20.5.3构造类型的基类和接口
构造类类型有一个直接基类,就像是一个简单类类型。如果泛型类声明没有指定基类,其基类为object。如果基类在泛型类声明中被指定,构造类型的基类通过将在基类声明中的每个类型参数,替代为构造类型对应类型实参而得到。给定泛型类声明
class B<U , V>{…} class G<T>:B<string , T[]>{…}
构造类型G
相似地,构造类、结构和接口类型有一组显式的基接口。显式基接口通过接受泛型类型声明中的显式基接口声明和某种替代而形成,这种替代是将在基接口声明中的每个类型参数,替代为构造类型的对应类型实参。
一个类型的所有基类和基接口通过递归地得到中间基类和接口的基类与接口而形成。例如,给定泛型类声明
class A {…} class B<T>:A{…} class C<T>:B<IComparable<T>>{…} class D<T>:C<T[]>{…} D<int>的基类是C<int[]>,B<IComparable<int[]>>,A和object。
20.5.4构造类型的成员
构造类型的非继承成员通过替代成员声明的类型实参,构造类型的对应类型实参而得到。
例如,给定泛型类声明
class Gen<T,U> { public T[,],a; public void G(int i ,T t , Gen<U, T> gt){…} public U Prop(get{…}) set{…}} public int H{double d}{…} }
构造类型Gen
public int[,][] a; public void G(int I , int[] t , Gen<IComparable<string>,int[] gt>){…} public IComparable<string> Prop{get{…} set{…}} public int H(double d){…}
注意替代处理是基于类型声明的语义意义的,并不是简单的基于文本的替代。在泛型类声明Gen中的成员a的类型是“T的二维数组” 因此在先前实例化类型中的成员a的类型是“int型的一维数组的二维数组”或int[,][]。
构造类型的继承成员以一种相似的方法得到。首先直接基类的所有成员是已经确定的。如果基类自身是构造类型这可能包括当前规则的递归应用。然后,继承成员的每一个通过将成员声明中的每个类型参数,替代为构造类型对应类型实参而被转换。
class B<U> { public U F(long index){…} } class D<T>:B<T[]> { public T G(string s){…} }
在先前的例子中,构造类型D
20.5.5构造类型的可访问性
当构造类型C
20.5.6转换
构造类型遵循与非泛型类型相同的规则(§6)。当应用这些规则时,构造类型的基类和接口必须按§20.5.3中所描述的方式确定。
除了那些在§6中所描述的之外,构造引用类型之间不存在特别的转换。尤其是,不像数组类型,构造引用类型不允许“co-variant”转换。也就是说,类型List不能转换到类型List(无论是隐式或显式)即使是B派生于A也是如此。同样,也不存在从List到List
class A {…} class B:A{…} class Colletion{…} class List<T>:Collection{…} class Test { void F() { List<A> listA = new List<A>(); List<B> listB= new List<B>(); Collection c1 = listA; //OK,List<A>是一个集合 Collection c2 = listB; //OK,List<B>是一个集合 List<A> a1 = listB; //错误,没有隐式的转换 List<A> a2 = (List<A>)listB; //错误,没有显式的转换 } }
20.5.7System.Nullable
在.NET基类库中定义了泛型结构类型System.Nullable
可以从一个null类型向任何由System.Nullable
Nullable<int> x = null; Nullable<string> y = null;
和下面的写法相同。
Nullable<int> x = Nullable<int>.default; Nullable<string> y = Nullable<string>.default;
20.5.8使用别名指令
使用别名可以命名一个封闭构造类型,但不能命名一个没有提供类型实参的泛型类型声明。例如
namespace N1 { class A<T> { class B{} } class C{} } namespace N2 { using W = N1.A; //错误,不能命名泛型类型 using X = N1.A.B; //错误,不能命名泛型类型 using Y = N1.A<int>; //ok,可以命名封闭构造类型 using Z = N1.C; //ok }
20.5.9特性
开放类型不能被用于特性内的任何地方。一个封闭构造类型可以被用作特性的实参,但不能被用作特性名,因为System.Attribute不可能是泛型类声明的基类。
class A:Attribute { public A(Type t){…} } class B<T>: Attribute{} //错误,不能将Attribute用作基类 class List<T> { [A(typeof(T))] T t; //错误,在特性中有开放类型 } class X { [A(typeof(List<int>))] int x; //ok,封闭构造类型 [B<int>] int y; //错误,无效的特性名字 }
以上就是C# 2.0 Specification (泛型三)的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!