C#6.0语言规范(九) 命名空间

C#程序使用命名空间进行组织。命名空间既可以用作程序的“内部”组织系统,也可以用作“外部”组织系统 - 一种呈现暴露给其他程序的程序元素的方式。

提供了使用指令(使用指令)以便于使用命名空间。

编译单位

compilation_unit定义了源文件的总体结构。编译单元由零个或多个using_directive组成,后跟零个或多个global_attributes,后跟零个或多个namespace_member_declaration

1 compilation_unit
2     : extern_alias_directive* using_directive* global_attributes? namespace_member_declaration*
3     ;

C#程序由一个或多个编译单元组成,每个编译单元都包含在一个单独的源文件中。编译C#程序时,将一起处理所有编译单元。因此,编译单元可以以循环方式彼此依赖。

using_directive编译单元号第影响global_attributesnamespace_member_declaration该编译单元的S,但对其他的编译单元没有影响。

编译单元的global_attributes(Attributes)允许指定目标程序集和模块的属性。程序集和模块充当类型的物理容器。组件可以由几个物理上分开的模块组成。

程序的每个编译单元的namespace_member_declaration将成员贡献给称为全局名称空间的单个声明空间。例如:

文件A.cs

class A {}

文件B.cs

class B {}

这两个编译单元对单个全局命名空间有贡献,在这种情况下,使用完全限定名称A和声明两个类B。因为两个编译单元对同一个声明空间有贡献,所以如果每个编译单元都包含一个具有相同名称的成员的声明,则会出错。

命名空间声明

namespace_declaration由关键字namespace,随后是命名空间名称和体,任选地接着用分号。

 1 namespace_declaration
 2     : ‘namespace‘ qualified_identifier namespace_body ‘;‘?
 3     ;
 4
 5 qualified_identifier
 6     : identifier (‘.‘ identifier)*
 7     ;
 8
 9 namespace_body
10     : ‘{‘ extern_alias_directive* using_directive* namespace_member_declaration* ‘}‘
11     ;

namespace_declaration可以如在顶层声明发生compilation_unit或作为另一个内的成员声明namespace_declaration。当namespace_declaration作为compilation_unit中的顶级声明出现时,该命名空间将成为全局命名空间的成员。当namespace_declaration另一个内发生namespace_declaration,内部命名空间成为外部命名空间的成员。在任何一种情况下,命名空间的名称在包含的命名空间中必须是唯一的。

命名空间是隐式的public,命名空间的声明不能包含任何访问修饰符。

namespace_body中,可选的using_directive导入其他名称空间,类型和成员的名称,允许直接引用它们而不是通过限定名称。可选的namespace_member_declaration将成员提供给命名空间的声明空间。请注意,所有using_directive必须出现在任何成员声明之前。

所述qualified_identifier一个的namespace_declaration可以是单个标识符或通过“分开的标识符序列.”令牌。后一种形式允许程序定义嵌套的命名空间,而不用词法嵌套几个命名空间声明。例如,

1 namespace N1.N2
2 {
3     class A {}
4
5     class B {}
6 }

在语义上等同于

1 namespace N1
2 {
3     namespace N2
4     {
5         class A {}
6
7         class B {}
8     }
9 }

命名空间是开放式的,具有相同完全限定名称的两个命名空间声明对同一声明空间(声明)有贡献。在这个例子中

1 namespace N1.N2
2 {
3     class A {}
4 }
5
6 namespace N1.N2
7 {
8     class B {}
9 }

以上两个命名空间声明提供相同的声明空间,在这种情况下,声明两个具有完全限定名N1.N2.AN1.N2.B。因为这两个声明对同一个声明空间有贡献,如果每个声明包含一个具有相同名称的成员的声明,那将是一个错误。

外部别名

一个extern_alias_directive引入了用作一个命名空间的别名的标识符。别名命名空间的规范是程序源代码的外部,也适用于别名命名空间的嵌套命名空间。

1 extern_alias_directive
2     : ‘extern‘ ‘alias‘ identifier ‘;‘
3     ;

extern_alias_directive的范围扩展到其直接包含的编译单元或命名空间体的using_directiveglobal_attributesnamespace_member_declaration

在包含extern_alias_directive的编译单元或命名空间体中,extern_alias_directive引入的标识符可用于引用别名命名空间。标识符是单词的编译时错误global

一个extern_alias_directive使得一个特定的编译单元或命名空间体中可用的别名,但它并没有任何新成员的基础声明空间。换句话说,extern_alias_directive不是传递性的,而是仅影响它出现的编译单元或命名空间体。

以下程序声明并使用两个extern别名,X并且Y每个别名代表不同命名空间层次结构的根:

 1 extern alias X;
 2 extern alias Y;
 3
 4 class Test
 5 {
 6     X::N.A a;
 7     X::N.B b1;
 8     Y::N.B b2;
 9     Y::N.C c;
10 }

该计划声明的extern别名的存在XY,但别名的实际定义外部程序。在同名的N.B类可以作为现在被引用X.N.BY.N.B,或者使用命名空间别名限定符,X::N.BY::N.B。如果程序声明了一个没有提供外部定义的extern别名,则会发生错误。

使用指令

使用指令有助于使用在其他命名空间中定义的命名空间和类型。使用指令会影响namespace_or_type_name s(名称空间和类型名称)和 simple_name s(简单名称)的名称解析过程,但与声明不同,使用指令不会将新成员提供给编译单元或命名空间的基础声明空间。用过的。

1 using_directive
2     : using_alias_directive
3     | using_namespace_directive
4     | using_static_directive
5     ;

using_alias_directive(使用别名指令)介绍了一个命名空间或类型的别名。

using_namespace_directive(使用命名空间指令)导入一个命名空间的类型成员。

using_static_directive(使用静态指令)导入嵌套类型和类型的静态成员。

一个的范围using_directive在延伸namespace_member_declaration直接包含它的编译单元或命名空间体的第 using_directive的范围特别不包括其对等的using_directive。因此,peer using_directive不会相互影响,并且它们的写入顺序是无关紧要的。

使用别名指令

using_alias_directive引入了用作用于直接包含编译单元或命名主体内的命名空间或类型的别名的标识符。

1 using_alias_directive
2     : ‘using‘ identifier ‘=‘ namespace_or_type_name ‘;‘
3     ;

在包含using_alias_directive的编译单元或命名空间体中的成员声明中,using_alias_directive引入的标识符可用于引用给定的命名空间或类型。例如:

 1 namespace N1.N2
 2 {
 3     class A {}
 4 }
 5
 6 namespace N3
 7 {
 8     using A = N1.N2.A;
 9
10     class B: A {}
11 }

上面,在N3命名空间中的成员声明中,A是一个别名N1.N2.A,因此类N3.B派生自类N1.N2.A。相同的效果可以通过创建别名来获得R用于N1.N2然后引用R.A

1 namespace N3
2 {
3     using R = N1.N2;
4
5     class B: R.A {}
6 }

所述标识符一个的using_alias_directive必须是编译单元或命名直接包含的声明空间内是唯一的using_alias_directive。例如:

1 namespace N3
2 {
3     class A {}
4 }
5
6 namespace N3
7 {
8     using A = N1.N2.A;        // Error, A already exists
9 }

上面N3已经包含一个成员A,因此using_alias_directive使用该标识符是编译时错误。同样,对于同一编译单元或命名空间体中的两个或多个using_alias_directive来说,使用相同名称声明别名是编译时错误。

一个using_alias_directive使得一个特定的编译单元或命名空间体中可用的别名,但它并没有任何新成员的基础声明空间。换句话说,using_alias_directive不是可传递的,而是仅影响它出现的编译单元或命名空间体。在这个例子中

1 namespace N3
2 {
3     using R = N1.N2;
4 }
5
6 namespace N3
7 {
8     class B: R.A {}            // Error, R unknown
9 }

引入的using_alias_directive的范围R仅扩展到包含它的名称空间主体中的成员声明,因此R在第二个名称空间声明中是未知的。但是,将using_alias_directive放在包含的编译单元中会导致别名在两个名称空间声明中都可用:

 1 using R = N1.N2;
 2
 3 namespace N3
 4 {
 5     class B: R.A {}
 6 }
 7
 8 namespace N3
 9 {
10     class C: R.A {}
11 }

与常规成员一样,using_alias_directive引入的名称在嵌套作用域中由类似命名的成员隐藏。在这个例子中

1 using R = N1.N2;
2
3 namespace N3
4 {
5     class R {}
6
7     class B: R.A {}        // Error, R has no member A
8 }

R.A在声明B原因中引用编译时错误,因为R引用N3.R,而不是N1.N2

写入using_alias_directive的顺序没有意义,using_alias_directive引用的namespace_or_type_name解析不受using_alias_directive本身或直接包含的编译单元或命名空间体中的其他using_directive的影响。换句话说,就解析了using_alias_directivenamespace_or_type_name,就好像直接包含编译单元或命名空间体没有using_directive一样。一个using_alias_directive可以通过但会影响extern_alias_directives在直接包含编译单元或命名空间体中。在这个例子中

 1 namespace N1.N2 {}
 2
 3 namespace N3
 4 {
 5     extern alias E;
 6
 7     using R1 = E.N;        // OK
 8
 9     using R2 = N1;         // OK
10
11     using R3 = N1.N2;      // OK
12
13     using R4 = R2.N2;      // Error, R2 unknown
14 }

最后一次using_alias_directive导致编译时错误,因为它不受第一个using_alias_directive的影响。第一个using_alias_directive不会导致错误,因为extern别名的范围E包括using_alias_directive

using_alias_directive可以为任何命名空间或类型创建别名,包括在其内出现的任何空间或类型嵌套在该命名空间中的命名空间。

通过别名访问命名空间或类型会产生与访问该命名空间或通过其声明的名称键入完全相同的结果。例如,给定

 1 namespace N1.N2
 2 {
 3     class A {}
 4 }
 5
 6 namespace N3
 7 {
 8     using R1 = N1;
 9     using R2 = N1.N2;
10
11     class B
12     {
13         N1.N2.A a;            // refers to N1.N2.A
14         R1.N2.A b;            // refers to N1.N2.A
15         R2.A c;               // refers to N1.N2.A
16     }
17 }

名称N1.N2.AR1.N2.A和,R2.A是等价的,都是指完全限定名称的类N1.N2.A

使用别名可以命名一个封闭的构造类型,但不能在不提供类型参数的情况下命名未绑定的泛型类型声明。例如:

 1 namespace N1
 2 {
 3     class A<T>
 4     {
 5         class B {}
 6     }
 7 }
 8
 9 namespace N2
10 {
11     using W = N1.A;          // Error, cannot name unbound generic type
12
13     using X = N1.A.B;        // Error, cannot name unbound generic type
14
15     using Y = N1.A<int>;     // Ok, can name closed constructed type
16
17     using Z<T> = N1.A<T>;    // Error, using alias cannot have type parameters
18 }

使用命名空间指令

using_namespace_directive出口包含在一个命名空间到直接包含编译单元或命名空间体的种类,使每个类型的标识符无资格使用。

1 using_namespace_directive
2     : ‘using‘ namespace_name ‘;‘
3     ;

在包含using_namespace_directive的编译单元或命名空间体中的成员声明中,可以直接引用给定命名空间中包含的类型。例如:

 1 namespace N1.N2
 2 {
 3     class A {}
 4 }
 5
 6 namespace N3
 7 {
 8     using N1.N2;
 9
10     class B: A {}
11 }

上面,在N3命名空间中的成员声明中,类型成员N1.N2直接可用,因此类N3.B派生自类N1.N2.A

一个using_namespace_directive进口包含在给定命名空间中的类型,但不导入嵌套的命名空间。在这个例子中

 1 namespace N1.N2
 2 {
 3     class A {}
 4 }
 5
 6 namespace N3
 7 {
 8     using N1;
 9
10     class B: N2.A {}        // Error, N2 unknown
11 }

using_namespace_directive进口类型包含在N1,但嵌套在没有命名空间N1。因此,在结果N2.A声明中引用B编译时错误,因为没有命名N2的成员在范围内。

using_alias_directive不同,using_namespace_directive可以导入其标识符已在封闭编译单元或命名空间体中定义的类型。实际上,using_namespace_directive导入的名称由封闭编译单元或命名空间体中的类似命名成员隐藏。例如:

 1 namespace N1.N2
 2 {
 3     class A {}
 4
 5     class B {}
 6 }
 7
 8 namespace N3
 9 {
10     using N1.N2;
11
12     class A {}
13 }

这里,在N3命名空间中的成员声明中,A引用N3.A而不是N1.N2.A

当在同一编译单元或命名空间体中使用usespace_directiveusing_static_directive s 导入的多个名称空间或类型包含相同名称的类型时,对该名称作为type_name的引用被认为是不明确的。在这个例子中

 1 namespace N1
 2 {
 3     class A {}
 4 }
 5
 6 namespace N2
 7 {
 8     class A {}
 9 }
10
11 namespace N3
12 {
13     using N1;
14
15     using N2;
16
17     class B: A {}                // Error, A is ambiguous
18 }

双方N1N2包含一个成员A,而且由于N3进口两种,引用AN3是一个编译时错误。在这种情况下,冲突可以通过引用的限定来解决A,或者通过引入选择特定的using_alias_directive来解决A。例如:

 1 namespace N3
 2 {
 3     using N1;
 4
 5     using N2;
 6
 7     using A = N1.A;
 8
 9     class B: A {}                // A means N1.A
10 }

此外,当在同一编译单元或命名空间体中使用definespace_directiveusing_static_directive s 导入的多个名称空间或类型包含相同名称的类型或成员时,对该名称作为simple_name的引用被认为是不明确的。在这个例子中

 1 namespace N1
 2 {
 3     class A {}
 4 }
 5
 6 class C
 7 {
 8     public static int A;
 9 }
10
11 namespace N2
12 {
13     using N1;
14     using static C;
15
16     class B
17     {
18         void M()
19         {
20             A a = new A();   // Ok, A is unambiguous as a type-name
21             A.Equals(2);     // Error, A is ambiguous as a simple-name
22         }
23     }
24 }

N1包含一个类型成员A,并C包含一个静态方法A,并且因为N2两者都是导入,所以A作为simple_name引用是不明确的并且是编译时错误。

using_alias_directive类似using_namespace_directive不会向编译单元或命名空间的基础声明空间提供任何新成员,而只会影响它出现的编译单元或命名空间主体。

namespace_name通过引用using_namespace_directive以同样的方式作为解决namespace_or_type_name通过引用using_alias_directive。因此,在同一编译单元或命名空间体中使用definespace_directive不会相互影响,并且可以按任何顺序编写。

使用静态指令

using_static_directive导入嵌套类型和静态成员的类型声明到直接包含编译单元或命名空间体直接包含,使得每个部件和类型的标识符无资格使用。

1 using_static_directive
2     : ‘using‘ ‘static‘ type_name ‘;‘
3     ;

在包含using_static_directive的编译单元或命名空间体中的成员声明中,可以直接引用直接包含在给定类型的声明中的可访问嵌套类型和静态成员(扩展方法除外)。例如:

 1 namespace N1
 2 {
 3     class A
 4     {
 5         public class B{}
 6         public static B M(){ return new B(); }
 7     }
 8 }
 9
10 namespace N2
11 {
12     using static N1.A;
13     class C
14     {
15         void N() { B b = M(); }
16     }
17 }

上面,在N2命名空间中的成员声明中,静态成员和嵌套类型N1.A是直接可用的,因此该方法N能够引用它们BM成员N1.A

一个using_static_directive特别是不直接导入扩展方法为静态方法,但使它们可用于扩展方法调用(扩展方法调用)。在这个例子中

 1 namespace N1
 2 {
 3     static class A
 4     {
 5         public static void M(this string s){}
 6     }
 7 }
 8
 9 namespace N2
10 {
11     using static N1.A;
12
13     class B
14     {
15         void N()
16         {
17             M("A");      // Error, M unknown
18             "B".M();     // Ok, M known as extension method
19             N1.A.M("C"); // Ok, fully qualified
20         }
21     }
22 }

using_static_directive进口扩展方法M包含在N1.A,但只作为一个扩展方法。因此,在结果M体中的第一个引用B.N导致编译时错误,因为没有命名M的成员在范围内。

using_static_directive只有出口构件和直接在给定类型声明类型,而不是成员和在基类声明类型。

ALL:示例

使用命名空间指令中讨论了多个using_namespace_directivesusing_static_directives之间的歧义。

命名空间成员

namespace_member_declaration或者是namespace_declaration(命名空间声明)或type_declaration(类型声明)。

1 namespace_member_declaration
2     : namespace_declaration
3     | type_declaration
4     ;

编译单元或命名空间体可以包含namespace_member_declaration,并且此类声明将新成员提供给包含编译单元或命名空间体的基础声明空间。

输入声明

type_declarationclass_declaration(类声明),一个struct_declaration(struct声明),一个interface_declaration(接口声明),一个enum_declaration(enum声明),或一个delegate_declaration(委托声明)。

1 type_declaration
2     : class_declaration
3     | struct_declaration
4     | interface_declaration
5     | enum_declaration
6     | delegate_declaration
7     ;

type_declaration可发生在编译单元或作为命名空间,类,或结构内一个成员声明的顶层声明。

当类型的类型声明T作为编译单元中的顶级声明出现时,新声明的类型的完全限定名称就是简单的T。当一个类型的类型声明T一个命名空间,类或结构内时,新声明的类型的完全限定名N.T,其中N是包含命名空间,类或结构的完全合格的名称。

在类或结构中声明的类型称为嵌套类型(嵌套类型)。

允许的访问修饰符和类型声明的默认访问权限取决于声明发生的上下文(声明的可访问性):

  • 在编译单元或命名空间中声明的类型可以具有publicinternal访问。默认为internal访问。
  • 在类中声明的类型可以有publicprotected internalprotectedinternal,或private访问。默认为private访问。
  • 在结构中声明的类型可以有publicinternalprivate访问。默认为private访问。

命名空间别名限定符

命名空间别名限定符 ::能够保证类型名称查找是通过引入新的类型和成员的影响。命名空间别名限定符始终出现在两个标识符之间,称为左侧和右侧标识符。与常规.限定符不同,限定符的左侧标识符::仅作为extern或使用别名查找。

qualified_alias_member定义如下:

1 qualified_alias_member
2     : identifier ‘::‘ identifier type_argument_list?
3     ;

qualified_alias_member可以用作一个namespace_or_type_name(命名空间和类型名称),或者如在左操作数member_access(成员访问)。

一个qualified_alias_member有两种形式:

  • N::I<A1, ..., Ak>,where NI表示标识符,<A1, ..., Ak>是一个类型参数列表。(K总是至少有一个。)
  • N::I其中NI表示标识符。(在这种情况下,K被认为是零。)

使用此表示法,qualified_alias_member的含义确定如下:

  • 如果N是标识符global,则搜索全局命名空间I

    • 如果全局命名空间包含名为的命名空间IK为零,则qualified_alias_member引用该命名空间。
    • 否则,如果全局命名空间包含一个名为的非泛型类型IK为零,则qualified_alias_member引用该类型。
    • 否则,如果全局命名空间包含名为I具有K类型参数的类型,则qualified_alias_member引用使用给定类型参数构造的类型。
    • 否则,qualified_alias_member未定义,并发生编译时错误。
  • 否则,从直接包含qualified_alias_member(如果有)的名称空间声明(Namespace声明)开始,继续每个封闭的名称空间声明(如果有的话),并以包含qualified_alias_member的编译单元结束,评估以下步骤,直到实体为位于:
    • 如果名称空间声明或编译单元包含与类型关联的using_alias_directiveN,则qualified_alias_member未定义,并发生编译时错误。
    • 否则,如果名称空间声明或编译单元包含与命名空间关联的extern_alias_directiveusing_alias_directiveN,则:
      • 如果与之关联的命名空间N包含名为的命名空间IK为零,则qualified_alias_member引用该命名空间。
      • 否则,如果与之关联的名称空间N包含名为的非泛型类型IK为零,则qualified_alias_member将引用该类型。
      • 否则,如果与之关联的名称空间N包含名为I具有K类型参数的类型,则qualified_alias_member引用使用给定类型参数构造的类型。
      • 否则,qualified_alias_member未定义,并发生编译时错误。
  • 否则,qualified_alias_member未定义,并发生编译时错误。

请注意,使用带有引用类型的别名的命名空间别名限定符会导致编译时错误。另请注意,如果标识符Nglobal,则在全局命名空间中执行查找,即使存在global与类型或命名空间关联的using别名也是如此。

别名的唯一性

每个编译单元和命名空间体都有一个单独的声明空间,用于外部别名和使用别名。因此,虽然extern别名或使用别名的名称在extern别名集合中必须是唯一的,并且使用在包含直接包含的编译单元或命名空间体中声明的别名,但允许别名与类型或名称空间具有相同的名称。只要它与::限定符一起使用。

在这个例子中

 1 namespace N
 2 {
 3     public class A {}
 4
 5     public class B {}
 6 }
 7
 8 namespace N
 9 {
10     using A = System.IO;
11
12     class X
13     {
14         A.Stream s1;            // Error, A is ambiguous
15
16         A::Stream s2;           // Ok
17     }
18 }

该名称A在第二个名称空间体中有两种可能的含义,因为类A和使用别名A都在范围内。因此,A限定名称A.Stream中的使用不明确并导致发生编译时错误。然而,使用A::预选赛并不是因为一个错误A的抬头只能作为一个命名空间别名。

原文地址:https://www.cnblogs.com/strengthen/p/9742645.html

时间: 2024-11-05 16:04:45

C#6.0语言规范(九) 命名空间的相关文章

C#6.0语言规范(十九) 文档注释

C#为程序员提供了一种机制,可以使用包含XML文本的特殊注释语法来记录他们的代码.在源代码文件中,具有特定形式的注释可用于指示工具从这些注释和它们之前的源代码元素生成XML.使用这种语法的注释称为文档注释.它们必须紧接在用户定义的类型(例如类,委托或接口)或成员(例如字段,事件,属性或方法)之前.XML生成工具称为文档生成器.(这个生成器可以是,但不一定是C#编译器本身.)文档生成器生成的输出称为文档文件.文档文件用作a的输入文档查看器 ; 用于生成类型信息及其相关文档的某种视觉显示的工具. 此

C#6.0语言规范(四) 类型

C#语言的类型分为两大类:值类型和引用类型.值类型和引用类型都可以是泛型类型,它们采用一个或多个类型参数.类型参数可以指定值类型和引用类型. 1 type 2 : value_type 3 | reference_type 4 | type_parameter 5 | type_unsafe 6 ; 类型的最终类别(指针)仅在不安全的代码中可用.这在Pointer类型中进一步讨论. 值类型与引用类型的不同之处在于值类型的变量直接包含它们的数据,而引用类型的变量存储对其数据的引用,后者称为对象.对

C#6.0语言规范(三) 基本概念

应用程序启动 具有入口点的程序集称为应用程序.运行应用程序时,会创建一个新的应用程序域.应用程序的几个不同实例可以同时存在于同一台机器上,并且每个实例都有自己的应用程序域. 应用程序域通过充当应用程序状态的容器来启用应用程序隔离.应用程序域充当应用程序中定义的类型及其使用的类库的容器和边界.加载到一个应用程序域中的类型与加载到另一个应用程序域中的相同类型不同,并且应用程序域之间不直接共享对象实例.例如,每个应用程序域都有自己的这些类型的静态变量副本,每个应用程序域最多运行一次类型的静态构造函数.

C#6.0语言规范(十) 类

类是可以包含数据成员(常量和字段),函数成员(方法,属性,事件,索引器,运算符,实例构造函数,析构函数和静态构造函数)和嵌套类型的数据结构.类类型支持继承,这是一种派生类可以扩展和专门化基类的机制. 类声明 一个class_declaration是type_declaration(类型声明,声明一个新的类). 1 class_declaration 2 : attributes? class_modifier* 'partial'? 'class' identifier type_paramet

C#6.0语言规范(七) 表达式

表达式是运算符和操作数的序列.本章定义了操作数和运算符的语法,求值顺序以及表达式的含义. 表达式分类 表达式分类为以下之一: 一个值.每个值都有一个关联的类型. 一个变量.每个变量都有一个关联的类型,即声明的变量类型. 命名空间.具有此分类的表达式只能显示为member_access(成员访问)的左侧.在任何其他上下文中,分类为命名空间的表达式会导致编译时错误. 一种.具有此分类的表达式只能显示为member_access(成员访问)的左侧,或者作为运算as符(作为运算符),is运算符(运算符)

C#6.0语言规范(十三) 接口

接口定义合同.实现接口的类或结构必须遵守其合同.接口可以从多个基接口继承,并且类或结构可以实现多个接口. 接口可以包含方法,属性,事件和索引器.接口本身不为它定义的成员提供实现.接口仅指定必须由实现接口的类或结构提供的成员. 接口声明 一个interface_declaration是type_declaration(类型声明,声明新的接口类型). 1 interface_declaration 2 : attributes? interface_modifier* 'partial'? 'int

C#6.0语言规范(十四) 枚举

一个枚举类型是一个独特的值类型(值类型)声明一组命名的常量. 这个例子 1 enum Color 2 { 3 Red, 4 Green, 5 Blue 6 } 声明了一个名为枚举类型Color与成员Red,Green和Blue. 枚举声明 枚举声明声明了一个新的枚举类型.枚举声明以关键字开头enum,并定义枚举的名称,可访问性,基础类型和成员. 1 enum_declaration 2 : attributes? enum_modifier* 'enum' identifier enum_bas

C#6.0语言规范(十五) 委托

委托启用其他语言(如C ++,Pascal和Modula)已使用函数指针进行寻址的方案.但是,与C ++函数指针不同,委托是完全面向对象的,与成员函数的C ++指针不同,委托封装了对象实例和方法. 委托声明定义了从类派生的类System.Delegate.委托实例封装了一个调用列表,该列表是一个或多个方法的列表,每个方法都被称为可调用实体.对于实例方法,可调用实体由该实例上的实例和方法组成.对于静态方法,可调用实体仅包含一个方法.使用适当的参数集调用委托实例会导致使用给定的参数集调用每个委托的可

C#6.0语言规范(十六) 异常

C#中的异常提供了一种结构化,统一且类型安全的方法来处理系统级和应用程序级错误条件.C#中的异常机制与C ++的异常机制非常相似,但有一些重要的区别: 在C#中,所有异常必须由派生自的类类型的实例表示System.Exception.在C ++中,任何类型的任何值都可用于表示异常. 在C#中,finally块(try语句)可用于编写在正常执行和异常条件下执行的终止代码.在没有重复代码的情况下,这样的代码很难用C ++编写. 在C#中,系统级异常(例如溢出,被零除和空取消引用)具有明确定义的异常类