泛型类声明

泛型类声明
泛型类声明是一种类的声明
它需要提供类型实参才能构成实际类型。

类声明可以有选择地定义类型形参

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

None.gif class - declaration:
None.gifattributesopt   
class - modifiersopt    class    identifier   type - parameter - listopt    class - baseopt
None.gif          type
- parameter - constraints - clausesopt    class - body   ;opt

 

只有提供了一个 type-parameter-list才可以为这个类声明提供 type-parameter-constraints-clauses

提供了 type-parameter-list 的类声明是一个泛型类声明。此外任何嵌套在泛型类声明或泛型结构声明中的类本身就是一个泛型类声明因为必须为包含类型提供类型形参才能创建构造类型。

除了明确指出的地方外泛型类声明与非泛型类声明遵循相同的规则。泛型类声明可嵌套在非泛型类声明中。

使用构造类型 (constructed type)引用泛型类。给定下面的泛型类声明

 

ExpandedBlockStart.gif ContractedBlock.gif class  List < T >   dot.gif {}

 

List<T>List<int> List<List<string>> 就是其构造类型的一些示例。使用一个或多个类型形参的构造类型例如 List<T>称为开放构造类型 (open constructed type)。不使用类型形参的构造类型(例如 List<int>)称为封闭构造类型 (closed constructed type)

泛型类型可根据类型形参的数目进行重载”;这就是说同一命名空间或外层类型声明中的两个类型声明可以使用相同标识符只要这两个声明具有不同数目的类型形参即可。

ExpandedBlockStart.gif ContractedBlock.gif class  C  dot.gif {}
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class  C < V >   dot.gif {}
None.gif
ExpandedBlockStart.gifContractedBlock.gif
struct  C < U,V >   dot.gif {}        //  Error, C with two type parameters defined twice
None.gif

ExpandedBlockStart.gifContractedBlock.gif
class  C < A,B >   dot.gif {}         //  Error, C with two type parameters defined twice
None.gif

类型名称解析

、简单名称解析 和成员访问、 过程中使用的类型查找规则均会考虑类型形参的数目。

泛型类声明的基接口必须满足唯一性规则。

类型形参

类型形参可在类声明中提供。每个类型形参都是一个简单标识符代表一个为创建构造类型而提供的类型实参的占位符。类型形参是将来提供的类型的形式占位符。而类型实参是在创建构造类型时替换类型形参的实际类型。

None.gif type - parameter - list:
None.gif
<    type - parameters    >
None.gif
None.giftype
- parameters:
None.gifattributesopt   type
- parameter
None.giftype
- parameters   ,   attributesopt   type - parameter
None.gif
None.giftype
- parameter:
None.gifidentifier
None.gif

类声明中的每个类型形参在该类的声明空间

中定义一个名称。因此,它不能与另一个类型形参或该类中声明的成员具有相同的名称。类型形参不能与类型本身具有相同的名称。

类上的类型形参的作用域包括 class-basetype-parameter-constraints-clauses class-body。与类的成员不同此作用域不会扩展到派生类。在其作用域中,类型形参可用作类型。

 

None.gif type:
None.gifvalue
- type
None.gifreference
- type
None.giftype
- parameter

 

由于类型形参可使用许多不同的实际类型实参进行实例化因此类型形参具有与其他类型稍微不同的操作和限制。这包括:

·         不能直接使用类型形参声明基类或接口

·         类型形参上的成员查找规则取决于应用到该类型形参的约束(如果有)。

·         类型形参的可用转换取决于应用到该类型形参的约束(如果有)。

·         如果事先不知道由类型形参给出的类型是引用类型不能将标识null 转换为该类型。不过,可以改为使用默认值表达式。此外,具有由类型形参给出的类型的值可以使用 == != null 进行比较,除非该类型形参具有值类型约束

·         仅当类型形参受 constructor-constraint 或值类型约束的约束时,才能将 new 表达式与类型形参联合使用。

·         不能在属性中的任何位置上使用类型形参。

·         不能在成员访问或类型名称中使用类型形参标识静态成员或嵌套类型

·         在不安全代码中,类型形参不能用作 unmanaged-type

作为类型类型形参纯粹是一个编译时构造。在运行时,每个类型形参都绑定到一个运行时类型,运行时类型是通过向泛型类型声明提供类型实参来指定的。因此,使用类型形参声明的变量的类型在运行时将是封闭构造类型。涉及类型形参的所有语句和表达式的运行时执行都使用作为该形参的类型实参提供的实际类型。

实例类型

每个类声明都有一个关联的构造类型即实例类型 (instance type)。对于泛型类声明,实例类型是通过从该类型声明创建构造类型来构成的,所提供的每个类型实参替换对应的类型形参。由于实例类型使用类型形参,因此只能在类型形参的作用域中使用该实例类型;也就是在类声明的内部。对于在类声明中编写的代码,实例类型为 this 的类型。对于非泛型类,实例类型就是所声明的类。下面显示几个类声明以及它们的实例类型: 

None.gifclass A<T>                       // instance type: A<T>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
class B dot.gif{}                   // instance type: A<T>.B
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
class C<U> dot.gif{}               // instance type: A<T>.C<U>
ExpandedBlockEnd.gif
}

None.gif
ExpandedBlockStart.gifContractedBlock.gif
class D dot.gif{}                       // instance type: D
None.gif

基规范

类声明中指定的基类可以是构造类类型。基类本身不能是类型形参,但在其作用域中可以包含类型形参。

 

ExpandedBlockStart.gif ContractedBlock.gif class  Extend < V > : V  dot.gif {}          //  Error, type parameter used as base class

 

泛型类声明不能使用 System.Attribute 作为直接或间接基类。

类声明中指定的基接口可以是构造接口类型。基接口本身不能是类型形参,但在其作用域中可以包含类型形参。下面的代码演示类实现和扩展构造类型的方法:

ExpandedBlockStart.gif ContractedBlock.gif class  C < U,V >   dot.gif {}
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface  I1 < V >   dot.gif {}
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class  D: C < string , int > , I1 < string >   dot.gif {}
None.gif
ExpandedBlockStart.gifContractedBlock.gif
class  E < T > : C < int ,T > , I1 < T >   dot.gif {}
None.gif

泛型类声明的基接口必须满足

唯一性规则。

如果类中的方法重写或实现基类或接口中的方法则必须为特定类型提供相应的方法。下面的代码演示如何重写和实现方法。对此做了进一步的解释。

None.gifclass C<U,V> 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
public virtual void M1(U x, List<V> y) dot.gif{dot.gif}
ExpandedBlockEnd.gif}

None.gif
None.gif
interface I1<V> 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gifV M2(V);
ExpandedBlockEnd.gif}

None.gif
None.gif
class D: C<string,int>, I1<string> 
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
public override void M1(string x, List<int> y) dot.gif{dot.gif}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public string M2(string x) dot.gif{dot.gif}
ExpandedBlockEnd.gif}

None.gif

泛型类的成员

泛型类的所有成员都可以直接或作为构造类型的一部分使用任何包容类 (enclosing class) 中的类型形参。当在运行时使用特定的封闭构造类型时,所出现的每个类型形参都被替换成为该构造类型提供的实际类型实参。例如

None.gif class  C < V >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
public V f1;
InBlock.gif
public C<V> f2 = null;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public C(V x) dot.gif{
InBlock.gif     
this.f1 = x;
InBlock.gif     
this.f2 = this;
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif
class  Application
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
static void Main() dot.gif{
InBlock.gif     C
<int> x1 = new C<int>(1);
InBlock.gif     Console.WriteLine(x1.f1);       
// Prints 1
InBlock.gif

InBlock.gif     C
<double> x2 = new C<double>(3.1415);
InBlock.gif     Console.WriteLine(x2.f1);       
// Prints 3.1415
ExpandedSubBlockEnd.gif
}

ExpandedBlockEnd.gif}

None.gif

在实例函数成员中

类型 this 是包含这些成员的声明的实例类型

除了使用类型形参作为类型以外泛型类声明中的成员与非泛型类的成员遵循相同的规则。下面几小节将讨论适用于特定种类的成员的附加规则。

泛型类中的静态字段

泛型类声明中的静态变量在相同封闭构造类型的所有实例之间共享但是不会在不同封闭构造类型的实例之间共享。不管静态变量的类型是否涉及任何类型形参,这些规则都适用。

例如

None.gifclass C<V>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
static int count = 0;
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public C() dot.gif{
InBlock.gif     count
++;
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static int Count dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif     
get dot.gifreturn count; }
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif 
None.gif
None.gif
class Application
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
static void Main() dot.gif{
InBlock.gif     C
<int> x1 = new C<int>();
InBlock.gif     Console.WriteLine(C
<int>.Count);       // Prints 1
InBlock.gif

InBlock.gif     C
<double> x2 = new C<double>();
InBlock.gif     Console.WriteLine(C
<int>.Count);       // Prints 1
InBlock.gif

InBlock.gif     C
<int> x3 = new C<int>();
InBlock.gif     Console.WriteLine(C
<int>.Count);       // Prints 2
ExpandedSubBlockEnd.gif
}

ExpandedBlockEnd.gif}

None.gif
None.gif
泛型类中的静态构造函数

泛型类中的静态构造函数用于初始化静态字段并为从该泛型类声明创建的每个不同封闭构造类型执行其他初始化操作。泛型类型声明的类型形参处于作用域中,并且可在静态构造函数的函数体中使用。

新的封闭构造类类型在第一次发生下列任一情况时进行初始化

·         创建该封闭构造类型的实例。

·         引用该封闭构造类型的任何静态成员

为了初始化新的封闭构造类类型需要先为该特定的封闭构造类型创建一组新的静态字段。将其中的每个静态字段初始化为默认值。下一步,为这些静态字段执行静态字段初始值设定项。最后,执行静态构造函数。

由于静态构造函数只为每个封闭构造类类型执行一次因此对于无法通过约束在编译时进行检查的类型形参来说此处是进行运行时检查的方便位置。例如,下面的类型使用静态构造函数检查类型实参是否为一个枚举:

None.gifclass Gen<T> where T: struct
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
static Gen() dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif     
if (!typeof(T).IsEnum) dot.gif{
InBlock.gif        
throw new ArgumentException("T must be an enum");
ExpandedSubBlockEnd.gif     }

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif
访问受保护成员

在泛型类声明中通过从该泛型类构造的任何类类型的实例可以对继承的受保护实例成员进行访问。具体而言,指定的用于访问 protected protected internal 实例成员的规则通过下面针对泛型的规则进行了扩充:

·         在泛型类 G 如果 E 的类型是从 G 构造的类类型或从 G 构造的类类型继承的类类型则使用 E.M 形式的 primary-expression 访问继承的受保护实例成员 M 是允许的。

在下面的示例中

None.gif class  C < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
protected T x;
ExpandedBlockEnd.gif}

None.gif
None.gif
class  D < T > : C < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
static void F() dot.gif{
InBlock.gif     D
<T> dt = new D<T>();
InBlock.gif     D
<int> di = new D<int>();
InBlock.gif     D
<string> ds = new D<string>();
InBlock.gif     dt.x 
= default(T);
InBlock.gif     di.x 
= 123;
InBlock.gif     ds.x 
= "test";
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

None.gif
None.gif

x 的三个赋值是允许的因为它们全都通过从该泛型类型构造的类类型的实例进行。

泛型类中的重载

泛型类声明中的方法、构造函数、索引器和运算符可以被重载。虽然声明的签名必须唯一,但是在替换类型实参时可能会导致出现完全相同的签名。在这样的情况下,重载解析的附加规则将挑选最明确的
成员。

下面的示例根据此规则演示有效和无效的重载

ExpandedBlockStart.gifContractedBlock.gifinterface I1<T> dot.gif{dot.gif}
None.gif
ExpandedBlockStart.gifContractedBlock.gif
interface I2<T> dot.gif{dot.gif}
None.gif
None.gif
class G1<U>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
int F1(U u);                // Overload resulotion for G<int>.F1
InBlock.gif
int F1(int i);                  // will pick non-generic
InBlock.gif

InBlock.gif
void F2(I1<U> a);           // Valid overload
InBlock.gif
void F2(I2<U> a);
ExpandedBlockEnd.gif}

None.gif
None.gif
class G2<U,V>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif
void F3(U u, V v);          // Valid, but overload resolution for
InBlock.gif
void F3(V v, U u);          // G2<int,int>.F3 will fail
InBlock.gif

InBlock.gif
void F4(U u, I1<V> v);      // Valid, but overload resolution for  
InBlock.gif
   void F4(I1<V> v, U u);     // G2<I1<int>,int>.F4 will fail
InBlock.gif

InBlock.gif
void F5(U u1, I1<V> v2); // Valid overload
InBlock.gif
void F5(V v1, U u2);
InBlock.gif
InBlock.gif
void F6(ref U u);           // valid overload
InBlock.gif
void F6(out V v);
ExpandedBlockEnd.gif}

None.gif
None.gif
形参数组方法和类型形参

可以在形参数组的类型中使用类型形参。例如,给定下面的声明

None.gif class  C < V >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
static void F(int x, int y, params V[] args);
ExpandedBlockEnd.gif}

None.gif
None.gif

对该方法的如下展开形式的调用

None.gif C < int > .F( 10 20 );
None.gifC
< object > .F( 10 20 30 40 );
None.gifC
< string > .F( 10 20 " hello " " goodbye " );
None.gif
None.gif

完全对应于

ExpandedBlockStart.gifContractedBlock.gifC<int>.F(1020new int[] dot.gif{});
ExpandedBlockStart.gifContractedBlock.gifC
<object>.F(1020new object[] dot.gif{3040});
ExpandedBlockStart.gifContractedBlock.gifC
<string>.F(1020new string[] dot.gif{"hello""goodbye"} );
None.gif
None.gif
重写和泛型类

和往常一样泛型类中的函数成员可以重写基类中的函数成员。在确定被重写的基成员时,必须通过替换类型实参来确定基类的成员。一旦确定了基类的成员,重写规则就与非泛型类
相同。

下面的示例演示重写规则如何在存在泛型的情况下起作用

None.gifabstract class C<T>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
public virtual T F() dot.gif{dot.gif}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public virtual C<T> G() dot.gif{dot.gif}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public virtual void H(C<T> x) dot.gif{dot.gif}
ExpandedBlockEnd.gif}

None.gif
None.gif
class D: C<string>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
public override string F() dot.gif{dot.gif}              // Ok
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
public override C<string> G() dot.gif{dot.gif}           // Ok
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
public override void H(C<T> x) dot.gif{dot.gif}      // Error, should be C<string>
ExpandedBlockEnd.gif
}

None.gif
None.gif
class E<T,U>: C<U>
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif
public override U F() dot.gif{dot.gif}               // Ok
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
public override C<U> G() dot.gif{dot.gif}            // Ok
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
public override void H(C<T> x) dot.gif{dot.gif}      // Error, should be C<U>
ExpandedBlockEnd.gif
}

None.gif
None.gif
泛型类中的运算符

泛型类声明可以定义运算符所遵循的规则与非泛型类声明相同。运算符声明中使用类声明的实例类型的方式必须与运算符的正常使用规则类似,具体如下:

·         一元运算符必须以该实例类型的单个参数为操作对象。一元的 ++ -- 运算符必须返回该实例类型或从该实例类型派生的类型。

·         二元运算符的参数中必须至少有一个属于该实例类型。

·         转换运算符的形参类型或返回类型必须属于该实例类型

下面演示泛型类中的有效运算符声明的一些示例

None.gif class  X < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static X<T> operator ++(X<T> operand) dot.gif{dot.gif}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static int operator *(X<T> op1, int op2) dot.gif{dot.gif}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static explicit operator X<T>(T value) dot.gif{dot.gif}
ExpandedBlockEnd.gif}

None.gif
None.gif

对于从源类型 S 转换到目标类型 T 的转换运算符在应用指定的规则时 S T 关联的任何类型形参都被视为与其他类型没有继承关系的唯一类型并忽略对那些类型形参的所有约束。

在下面的示例中

ExpandedBlockStart.gif ContractedBlock.gif class  C < T >   dot.gif {dot.gif}
None.gif
None.gif
class  D < T > : C < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static implicit operator C<int>(D<T> value) dot.gif{dot.gif}       // Ok
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
public static implicit operator C<string>(D<T> value) dot.gif{dot.gif} // Ok
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif
public static implicit operator C<T>(D<T> value) dot.gif{dot.gif}      // Error
ExpandedBlockEnd.gif
}

None.gif
None.gif

前两个运算符声明是允许的T int 以及 string 分别被视为没有关系的唯一类型。但是,第三个运算符是错误的,因为 C<T> D<T> 的基类。

对于某些类型实参可以声明这样的运算符即这些运算符指定了已经作为预定义转换而存在的转换。在下面的示例中

None.gif struct  Convertible < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static implicit operator Convertible<T>(T value) dot.gif{dot.gif}
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
public static explicit operator T(Convertible<T> value) dot.gif{dot.gif}
ExpandedBlockEnd.gif}

None.gif

当把类型

object 指定为 T 的类型实参时 第二个运算符将声明一个已经存在的转换 存在从任何类型到类型 object 的隐式转换 因此也存在显式转换

在两个类型之间存在预定义转换的情况下这些类型之间的任何用户定义的转换将被忽略。具体而言:

·         如果存在从类型 S 到类型T 的预定义隐式转换,则从S T 的所有用户定义的转换(隐式或显式)将被忽略。

·         如果存在从类型S 到类型T 的预定义显式转换,则从 S T 的所有用户定义的显式转换将被忽略。但是,仍然会考虑从 S T 的用户定义的隐式转换。

对于除 object 以外的所有类型上面的 Convertible<T> 类型声明的运算符都不会与预定义的转换发生冲突。例如

 

ExpandedBlockStart.gif ContractedBlock.gif void  F( int  i, Convertible < int >  n)  dot.gif {
InBlock.gif
= n;                          // Error
InBlock.gif
= (int)n;                        // User-defined explicit conversion
InBlock.gif
= i;                          // User-defined implicit conversion
InBlock.gif
= (Convertible<int>)i;    // User-defined implicit conversion
ExpandedBlockEnd.gif
}

 

但是对于类型 object除了下面这个特例之外预定义的转换将在其他所有情况下隐藏用户定义的
转换

 

ExpandedBlockStart.gif ContractedBlock.gif void  F( object  o, Convertible < object >  n)  dot.gif {
InBlock.gif
= n;                          // Pre-defined boxing conversion
InBlock.gif
= (object)n;                     // Pre-defined boxing conversion
InBlock.gif
= o;                          // User-defined implicit conversion
InBlock.gif
= (Convertible<object>)o; // Pre-defined unboxing conversion
ExpandedBlockEnd.gif
}

 

泛型类中的嵌套类型

泛型类声明可以包含嵌套的类型声明。包容类的类型形参可以在嵌套类型中使用。嵌套类型声明可以包含仅适用于该嵌套类型的附加类型形参。

泛型类声明中包含的每个类型声明都隐式地是泛型类型声明。在编写对嵌套在泛型类型中的类型的引用时,必须指定其包容构造类型(包括其类型实参)。但是可在外层类中不加限定地使用嵌套类型;在构造嵌套类型时可以隐式地使用外层类的实例类型。下面的示例演示三种不同的引用从 Inner 创建的构造类型的正确方法;前两种方法是等效的:

None.gif class  Outer < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif   
class Inner<U>
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
ExpandedSubBlockStart.gifContractedSubBlock.gif     
public static void F(T t, U u) dot.gif{dot.gif}
ExpandedSubBlockEnd.gif}

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif
static void F(T t) dot.gif{
InBlock.gif     Outer
<T>.Inner<string>.F(t, "abc");       // These two statements have
InBlock.gif
     Inner<string>.F(t, "abc");                // the same effect
InBlock.gif

InBlock.gif     Outer
<int>.Inner<string>.F(3"abc");  // This type is different
InBlock.gif

InBlock.gif     Outer.Inner
<string>.F(t, "abc");          // Error, Outer needs type arg
ExpandedSubBlockEnd.gif
}

ExpandedBlockEnd.gif}

None.gif
None.gif

嵌套类型中的类型形参可以隐藏外层类型中声明的成员或类型形参,但这是一种不好的编程风格

None.gif class  Outer < T >
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif
class Inner<T>       // Valid, hides Outer’s T
ExpandedSubBlockStart.gifContractedSubBlock.gif
dot.gif{
InBlock.gif     
public T t;       // Refers to Inner’s T
ExpandedSubBlockEnd.gif
}

ExpandedBlockEnd.gif}

None.gif

转载于:https://www.cnblogs.com/ITmuse/archive/2007/11/20/965151.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值