C#2.0 Specification(泛型一)

这篇文章是翻译的微软的技术文章 .供学习c#的朋友参考,请勿用于商业目的。 http://msdn.microsoft.com/vcsharp/team/language/default.aspx

由于这一章非常长可能需要分几篇:)

20 .泛型

20.1 泛型类声明

泛型类声明是一个需要提供类型参数以形成实际类型的类的声明。

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

class-declaration : (类声明)

attributes opt class-modifiers opt class identifier opt type-parameter-list opt class –base opt type-parameter-constraints-clause opt class-body ; opt ( 特性 可选 类修饰符 可选 类标识符 可选 类型参数列表 可选 基类 可选 类型参数约束语句 可选 类体 ; 可选 )

除非提供了类型参数列表,类声明可以不提供类型参数化约束语句。

提供了类型参数列表的类声明是一个泛型类声明。此外,任何嵌入到泛型类声明或泛型结构声明中的类,自身是一个泛型类声明,因为必须提供包含类型的类型参数以创建构造类型( constructed type );

泛型类通过使用构造类型而被引用(§ 20.5)。给定泛型类声明

class List

  1<t>{} 
  2
  3这是构造类型的一些例子,  List<t> ,  List<int> 和  List<list<string>&gt; 。构造类型可以使用一个或多个参数,例如  List<t> 被称为开放构造类型(  open constructed type  )  。不使用类型参数的构造类型,例如  List<int> 被称为封闭构造类型(  closed constructed type  )  。 
  4
  5泛型类型不可以被“重载”;也就是说,和普通类型一样在一个作用域内,泛型类型必须被唯一地命名。 
  6
  7  
  8
  9
 10class C{} 
 11
 12class C<v>{}//  错误,  C  定义了两次 
 13
 14class C<u,v>{}//  错误,  C  定义了两次 
 15
 16然而在非限定类型名字查找(§  20.9.3)中使用的类型查找规则和成员访问(§20.9.4),确实考虑到了类型参数的个数。 
 17
 18###  20.1.1  类型参数 
 19
 20类型参数可以在一个类声明上提供。每个类型参数是一个简单的标识符,它指示了用来创建一个构造类型的类型参数的占位符。类型参数是在后面将要被提供的类型的形式占位符。相反,类型参数§  20.5.1  )只是在构造类型被引用时,实际类型的一个替代。 
 21
 22_ type-parameter-list  _ :(类型参数列表:) 
 23
 24&lt; _type-parameters_ &gt; (  &lt; 类型参数  &gt; ) 
 25
 26_ type-parameters  _ :(类型参数:) 
 27
 28_type-parameter_ (类型参数) 
 29
 30_type-parameters type-parameter_ (类型参数,类型参数) 
 31
 32_ type-parameter  _ :(类型参数:) 
 33
 34_attributes_ opt  _identifier_ (特性  可选  标识符) 
 35
 36在类声明中的每个类型参数在类的声明空间(§  3.3)定义了一个名字。由此,它不能和另一个类型参数或在类中声明的成员有同样的名字。类型参数不能和类型自身有同样的名字。 
 37
 38在一个类中的类型参数的作用域(§  3.7),包括基类 、 类型参数约束语句和类体。不像类的成员,它没有扩展到派生类。在其作用域之内,类型参数可以被用作一个类型。 
 39
 40_type_ (类型): 
 41
 42_value-type_ (值类型) 
 43
 44_reference-type_ (引用类型) 
 45
 46_type-parameter_ (类型参数) 
 47
 48由于类型参数可以被许多不同的实际类型实参所实例化,类型参数与其他类型相比将略微有一些不同的操作和限制。包括如下内容。 
 49
 50  * 类型参数不能用于直接声明一个基类型或者接口 
 51  * 对于在类型参数上的成员查找规则,如果约束存在,则依赖于应用到该类型参数的约束。更详细地说明参看§  20.7.4  。 
 52
 53
 54
 55  
 56
 57
 58  * 类型参数可行的转换依赖于应用到该类型参数上的约束(如果有的话)。详细地说明参看§  20.7.4  。 
 59  * 字面  null  不能被转换到由类型参数所给定的类型,除非类型参数是由一个类约束(§  20.7.4  )所约束。然而可以使用一个默认值表达式(§  20.8.1  )代替。此外,由一个类型参数给定的类型的值可以使用“  ==  ”和“  !=  ”(§  20.8.4  )与  null  进行比较。 
 60  * 如果类型参数通过一个构造函数约束(  constructor-constraint  )(§  20.7  )而约束,  new  表达式只能用过一个类型参数而被使用。 
 61  * 类型参数不能用于特性内的任何地方。 
 62  * 类型参数不能用于成员访问,或者表示一个静态成员或者嵌套类型的类型名字(§  20.9.1  、§  20.9.4  )。 
 63  * 在不安全代码中,类型参数不能被用作托管类型(§  18.2  )。 
 64
 65
 66
 67作为一种类型,类型参数纯粹只是一个编译时构件。在运行时,每个类型参数被绑定到运行时类型,它是通过泛型类型声明所提供的类型实参所指定的。为此,在运行时,使用类型参数声明的变量类型是一个封闭类型(  closed type  )(§  20.5.2)。所有语句和表达式在运行时执行所使用的类型参数,都是由那个参数作为类型实参而提供的实际类型。 
 68
 69###  20.1.2  实例类型 
 70
 71每个类声明都有与之关联的构造类型,即实例类型  (instance type)  。  对于一个泛型类声明,实例类型通过创建一个来自于类型声明的构造类型(§  20.4  )而形成,它使用对应于类型参数的每一个类型实参。由于实例化类型使用类型参数,在类型参数作用域内(类声明之内),它是唯一有效的。实例类型在类声明中是  this  的类型。对于非泛型类,实例类型只是一个声明类型。下面展示了几个声明类,以及它们的实例类型。 
 72
 73class A<t> //  实例类型:  A<t>
 74
 75{ 
 76
 77class B{}  //  实例类型:  A<t>.B 
 78
 79class C<u>{}  //  实例类型:  A<t>.C<u>
 80
 81} 
 82
 83class D{}  //  实例类型:  D 
 84
 85###  20.1.3  基类规范 
 86
 87在类声明中指定的基类可以是一个构造类型(§  20.5  )。一个基类其自身不能是一个类型参数,但在其作用域内可以包含类型参数。 
 88
 89  
 90
 91
 92class Extend<v>: V{}//  错误,类型参数被用作基类 
 93
 94泛型类声明不能使用  System.Attribute  作为直接或间接基类。 
 95
 96在一个类声明中指定的基接口可以是构造接口类型(§  20.5)。基接口自身不能是类型参数,但在其作用域内可以包含类型参数,下面的代码演示了如何实现和扩展构造类型。 
 97
 98class C<u,v>{} 
 99
100Interface I1<v>{} 
101
102class D:C<string ,="" int="">,I1<string>{} 
103
104class E<t>:C<int,t> ,I1<t>{} 
105
106泛型类型声明的基接口必须满足§  20.3.1中所描述的唯一性规则。 
107
108从基类或接口重写或实现方法的类的方法,必须提供特定类型的合适方法。下面的代码演示了方法如何被重写和实现。这将会在§  20.1.10中进一步解释。 
109
110class C<u,v>
111
112{ 
113
114public virtual void  M1(U x , List<v> y){…} 
115
116} 
117
118interface I1<v>
119
120{ 
121
122V  M2(V x); 
123
124} 
125
126class D:C<string ,="" int="">,I1<string>
127
128{ 
129
130public override void M1(string x , List<int> y){…} 
131
132public string M2(string x){…} 
133
134} 
135
136###  20.1.4  泛型类的成员 
137
138泛型类的所有成员都可以直接地或者作为构造类型的一部分,从任何封闭类(  enclosing class  )中使用类型参数。当特定的封闭构造类型在运行时被使用时,类型参数的每次使用都由构造类型所提供的实际类型实参所代替。例如 
139
140class C<v>
141
142{ 
143
144public V f1; 
145
146public C<v> f2=null; 
147
148  
149
150
151public C(V x){ 
152
153this.f1 = x; 
154
155this.f2 = this; 
156
157} 
158
159} 
160
161class Application 
162
163{ 
164
165static void  Main  (){ 
166
167C<int> x1= new C<int>(1); 
168
169Console.WriteLine(x1.f1);  //  打印  1 
170
171C<double> x2 = new C<double>(3.1415); 
172
173Console.WriteLine(x2.f1); //  打印  3.1415 
174
175} 
176
177} 
178
179在实例函数成员之内,  this  的类型就是声明的实例类型(§  20.1.2)。 
180
181除了使用类型参数作为类型和成员,在泛型类声明中也遵循和非泛型类成员相同的规则。适用于特定种类成员的附加规则将在后面几节进行讨论。 
182
183###  20.1.5  泛型类中的静态字段 
184
185在一个泛型类声明中的静态变量,在相同封闭构造类型(§  20.5.2)所有实例中被共享,但在不同封闭构造类型的实例中  [1]  ,是不被共享的。这些规则不管静态变量的类型包含那种类型参数都适用。 
186
187例如 
188
189class C<v>
190
191{ 
192
193static int count = 0; 
194
195public C() 
196
197{ 
198
199count++; 
200
201} 
202
203public static int Count{ 
204
205get{return count;} 
206
207} 
208
209} 
210
211class Application 
212
213{ 
214
215static void  Main  () 
216
217{ 
218
219C<int> x1 = new C<int>(); 
220
221Console.WriteLine(C<int>.Count);//  打印  1 
222
223C<double> x2 = new C<double>(); 
224
225Console.WriteLine(C<int>.Count);//  打印  1 
226
227C<int> x3 = new C<int>(); 
228
229Console.WriteLine(C<int>.Count);//  打印  2 
230
231} 
232
233} 
234
235  
236
237
238* * *
239
240[1]  这是很容易理解的,因为在运行时,不同的封闭构造类型,是属于不同的类型,比如  List<int> 和  List<string> 这二者的实例是不能共享静态变量的。</string></int></int></int></int></int></double></double></int></int></int></v></double></double></int></int></v></v></int></string></string></v></v></u,v></t></int,t></t></string></string></v></u,v></v></u></t></u></t></t></t></u,v></v></int></t></list<string></int></t></t>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus