C# 2.0 Specification (四)

这段比较短就先干掉了:)

23 不完整类型

23.1 不完整类型声明

新类型修饰符 partial 用于在多个部分中定义一个类型。为了确保和现存程序的兼容性,这个修饰符和其他修饰符(比如get和set)是不同的,它不是一个关键字,并且它必须紧邻出现在关键字class ,struct或者interface之前。

l class-declaration (类声明)
attributes opt class-modifiers opt _ partial _ opt _ class _ identifier type-parameter-list opt
class-base opt type-parameter-constraints-clausesopt class-body _ ; _ opt

(特性 可选 类修饰符 可选 partial 可选 class 标识符

类型参数列表 可选 :基类 可选 类型参数约束语句 可选 类体; 可选 )

l struct-declaration: (结构声明)
attributesopt struct-modifiersopt _ partial _ opt _ struct _ identifier type-parameter-listopt
struct-interfacesopt type-parameter-constraints-clausesopt struct-body _ ; _ opt

(特性 可选 结构修饰符 可选 partial 可选 struct 标识符

类型参数列表 可选

结构接口 可选 类型参数约束语句 可选

结构体; 可选 )

l interface-declaration: (接口声明)
attributesopt interface-modifiersopt _ partial _ opt _ interface _ identifier type-parameter-listopt
interface-baseopt type-parameter-constraints-clausesopt interface-body _ ; _ opt

(特性 可选 接口修饰符 可选 partial 可选 interface 标识符

类型参数列表 可选

基接口 可选 类型参数约束语句 可选

接口体 ; 可选 )

不完整类型声明的每个部分都必须包含 partial修饰符,并且和其他部分必须被声明在相同的命名空间。partial修饰符表明该类型声明的附加部分可以存在于其他某个地方,但这种附加部分的存在并不是必需的;在一个单一类型声明中包含partial修饰符也是合理的。

不完整类型的所有部分必须放在一起编译,这样它们就可以在编译时被融合。特别的是,不完整类型不容许对已经被编译的类型进行扩展。

嵌套类型( nested type)可以通过使用partial修饰符而声明在多个地方。典型的情况是,包含类型(也就是包含嵌套类型的类型)同样使用partial声明,而嵌套类型的各个部分也在包含类型的不同部分中声明。

partial修饰符不能用在委托或枚举声明中。

23.1 特性

不完整类型的特性通过以不定的 (unspecified)顺序组合各个部分的特性而确定。如果一个特性被放在不完整类型的多个部分,它等价于在该类型上多次指定该特性。例如,这两个部分

[Attr1, Attr2("hello")]
partial class A {}

[Attr3, Attr2("goodbye")]
partial class A {}

等价于如下声明。

[Attr1, Attr2("hello"), Attr3, Attr2("goodbye")]
class A {}

类型参数上的特性也以相同的风格组合。

23.1.2 修饰符

当不完整类型声明包含访问说明( public,protected,internal和private)时,它必须与其它部分的访问说明一致。如果不完整类型的各个部分都不包含访问说明,该类型将被赋予适当的默认可访问性(§3.5.1)。

如果嵌套类型的一个或多个不完整声明包含 new修饰符,并且如果嵌套类型隐藏了一个继承成员,将不会有任何警告。(§3.7.12)

如果类的一个或多个不完整声明包含 abstract修饰符,那么这个类就是抽象的(§10.1.1.1),反之就是非抽象的。

注意,一个类不能同时既是抽象的又是密封的( sealed)。

当 unsafe 修饰符被用于一个不完整类型声明时,只有特定的部分被认为是不安全上下 [unsafe contex (§ 18.1 )) ] 。

23.1.3 类型参数和约束

如果泛型类型在多个部分被声明,每个部分都必须说明类型参数。每个部分都必须有相同数量的类型参数,并且对于每个类型参数必须有相同的名字和顺序。

当不完整泛型声明包含类型参数约束( where 语句),该约束必须和其他部分的约束一致。特别的是,包含约束的每个部分必须具有相同集合类型参数的约束,并且对于每个类型参数,

类、接口和构造函数约束的集合必须是相同的。如果不完整泛型的任何部分都没有指定约束,类型参数就被认为是不带约束的。

示例

partial class Dictionary

  1<k,v>   
  2where K: IComparable<k>   
  3where V: IKeyProvider<k>, IPersistable   
  4{   
  5...   
  6} 
  7
  8partial class Dictionary<k,v>   
  9where V: IPersistable, IKeyProvider<k>   
 10where K: IComparable<k>   
 11{   
 12...   
 13} 
 14
 15partial class Dictionary<k,v>   
 16{   
 17...   
 18} 
 19
 20是正确的,因为这些包含约束的部分有效地指定了类、接口的相同集合,以及相应相同集合的类型参数的构造函数约束。 
 21
 22###  23.1.4  基类 
 23
 24当不完整类声明包含基类说明时,它必须与包含基类说明的所有其他部分一致。如果不完整类声明的任何部分都不包含基类声明,那么基类将是  System.Object  (§  10.1.2.1  )。 
 25
 26###  23.1.5  基接口 
 27
 28在多个部分中声明的类型的基接口集合,是在各个部分中指定的基接口的联合。一个特定的基接口在每个部分中只能被命名一次,但可以在多个部分中命名相同的基接口。但对于任何给出的基接口成员只能有唯一的实现。 
 29
 30在例子 
 31
 32partial class C: IA, IB {...} 
 33
 34partial class C: IC {...} 
 35
 36partial class C: IA, IB {...} 
 37
 38中类  C  的基接口是  IA,IB  和  IC  。 
 39
 40  
 41
 42
 43通常,在接口声明的部分中提供接口的实现;但这不是必需的。一个部分可以为声明在另一个部分中的接口提供实现。 
 44
 45partial class X   
 46{   
 47int IComparable.CompareTo(object o) {...}   
 48} 
 49
 50partial class X: IComparable   
 51{   
 52...   
 53} 
 54
 55###  23.1.6  成员 
 56
 57声明在多个部分中的类型的成员只是在各个部分中声明的成员的联合。类型声明的所有部分的内容共享相同的声明空间(§  3.3  ),并且每个成员(§  3.7  )的作用域扩展到所有部分的内容。任何成员的所有可访问域总是包含封闭类型的所有部分;在一个部分中声明的  private  成员可以随意的在另一个部分访问。在一个类型的多个部分中声明相同的成员将造成编译时错误,除非该成员是一个带有  partial  修饰符的成员。 
 58
 59partial class A   
 60{   
 61int x;  //  错误  ,  不能多次声明  x 
 62
 63partial class Inner  // Ok, Inner  是不完整类型    
 64{   
 65int y;   
 66}   
 67} 
 68
 69partial class A   
 70{   
 71int x;  //  错误,不能多次声明  x 
 72
 73partial class Inner  // Ok, Inner  是不完整类型    
 74{   
 75int z;   
 76}   
 77} 
 78
 79尽管一个类型中成员的次序对于  C#  代码并不是太重要,但在面对其他语言和环境时却可能是很重要的。在这样的情况下,在多个部分中声明的类型内成员次序将是未定义的。 
 80
 81  
 82
 83
 84###  23.2  名字绑定 
 85
 86虽然可扩展类型的每个部分必须声明在相同的命名空间,但这些部分也可以写在不同的命名空间中。为此,对于各个部分可以使用不同的  using  指令(§  9.3  )。当在一个部分中解释简单名字(§  7.5.2  )时,只有包含该部分的命名空间  using  指令被考虑。这将使得在不同部分的相同标识符表示不同的意义。 
 87
 88namespace N   
 89{   
 90using List = System.Collections.ArrayList; 
 91
 92partial class A   
 93{   
 94List x;  // x  具有类型  System.Collections.ArrayList   
 95}   
 96} 
 97
 98namespace N   
 99{   
100using List = Widgets.LinkedList; 
101
102partial class A   
103{   
104List y;  // y  具有类型  Widgets.LinkedList   
105}   
106}</k,v></k></k></k,v></k></k></k,v>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus