接(泛型一)
这篇文章是翻译的微软的技术文章.供学习c#的朋友参考,请勿用于商业目的。http://msdn.microsoft.com/vcsharp/team/language/default.aspx
20.1.6泛型类中的静态构造函数
在泛型类中的静态构造函数被用于初始化静态字段,为每个从特定泛型类声明中创建的不同的封闭构造类型,执行其他初始化。泛型类型声明的类型参数在作用域之内,可以在静态构造函数体内被使用。
如果下列情形之一发生,一个新的封闭构造类类型将被首次初始化。
一个封闭构造类型的实例被创建时
封闭构造类型的任何静态成员被引用时
为了初始化一个新的封闭的构造类类型,首先那个特定封闭类型的一组新静态字段(§20.1.5)将会被创建。每个静态字段都被初始化为其默认值(§5.2)。接着,静态字段初始化器(§10.4.5.1)将为这些静态字段执行。最后静态构造函数将被执行。
由于静态构造函数将为每个封闭构造类类型执行一次,那么在不能通过约束(§20.7)检查的类型参数上实施运行时检查,将会很方便。例如,下面的类型使用一个静态构造函数检查一个类型参数是否是一个引用类型。
class Gen<T>
{
static Gen(){
if((object)T.default != null){
throw new ArgumentException(“T must be a reference type”);
}
}
}
20.1.7 访问受保护的成员
在一个泛型类声明中,对于继承的受保护的实例成员的访问是允许的,通过从泛型类构造的任何类型的实例就可以做到。尤其是,用于访问§3.5.3中指定的protected和protected internal实例成员的规则,对于泛型使用如下的规则进行了扩充。
在一个泛型类G中,对于一个继承的受保护的实例成员M,使用E.M的基本表达式是允许的,前提是E的类型是一个从G构造的类类型,或继承于一个从G构造的类类型的类类型。
在例子
class C<T>
{
protected T x;
}
class D<T> :C<T>
{
static void F(){
D<T> dt = new D<T>();
D<int> di = new D<int>();
D<string> ds = new D<string>();
dt.x = T.default;
di.x = 123;
ds.x = “test”;
}
}
三个对x的赋值语句都是允许的,因为它们都通过从泛型构造的类类型的实例发生。
20.1.8在泛型类中重载
在一个泛型类声明中的方法、构造函数、索引器和运算符可以被重载。但为了避免在构造类中的歧义,这些重载是受约束的。在同一个泛型类声明中使用相同的名字声明的两个函数成员必须具有这样的参数类型,也就是封闭构造类型中不能出现两个成员使用相同的名字和签名。当考虑所有可能的封闭构造类型时,这条规则包含了在当前程序中目前不存在的类型是实参,但它仍然是可能出现的[1]。在类型参数上的类型约束由于这条规则的目的而被忽略了。
下面的例子根据这条规则展示了有效和无效的重载。
nterface I1<T> {…}
interface I2<T>{…}
class G1<U>
{
long F1(U u); //无效重载,G<int>将会有使用相同签名的两个成员
int F1(int i);
void F2(U u1, U u2); //有效重载,对于U没有类型参数
void F2(int I , string s); //可能同时是int和string
void F3(I1<U>a); //有效重载
void F3(I2<U>a);
void F4(U a); //有效重载
void F4(U[] a);}
class G2<U,V>
{
void F5(U u , V v); //无效重载,G2<int , int>将会有两个签名相同的成员
void F5(V v, U u);
void F6(U u , I1<V> v);//无效重载,G2<I1<int>,int>将会有两个签名相同的成员
void F6(I1<V> v , U u);
void F7(U u1,I1<V> V2);//有效的重载,U不可能同时是V和I1<V>
void F7(V v1 , U u2);
void F8(ref U u); //无效重载
void F8(out V v);
}
class C1{…}
class C2{…}
class G3<U , V> where U:C1 where V:C2
{
void F9(U u); //无效重载,当检查重载时,在U和V上的约束将被忽略
void F9(V v);
}
20.1.9参数数组方法和类型参数
类型参数可以被用在参数数组的类型中。例如,给定声明
class C<V>
{
static void F(int x, int y ,params V[] args);
}
方法的扩展形式的如下调用
C<int>.F(10, 20);
C<object>.F(10,20,30,40);
C<string>.F(10,20,”hello”,”goodbye”);
对应于如下形式:
C<int>.F(10,20, new int[]{});
C<object>.F(10,20,new object[]{30,40});
C<string>.F(10,20,new string[](“hello”,”goodbye”));
20.1.10重写和泛型类
在泛型类中的函数成员可以重写基类中的函数成员。如果基类是一个非泛型类型或封闭构造类型,那么任何重写函数成员不能有包含类型参数的组成类型。然而,如果一个基类是一个开放构造类型,那么重写函数成员可以使用在其声明中的类型参数。当重写基类成员时,基类成员必须通过替换类型实参而被确定,如§20.5.4中所描述的。一旦基类的成员被确定,用于重写的规则和非泛型类是一样的。
下面的例子演示了对于现有的泛型其重写规则是如何工作的。
abstract class C<T>
{
public virtual T F(){…}
public virtual C<T> G(){…}
public virtual void H(C<T> x ){…}
}
class D:C<string>
{
public override string F(){…}//OK