现在的位置: 首页 > 综合 > 正文

C# Language Specification 1.2 之三 基本概念

2012年08月06日 ⁄ 综合 ⁄ 共 3834字 ⁄ 字号 评论关闭

1. 基本概念

1.1 应用程序启动

具有入口点 (entry point) 的程序集称为应用程序 (application)。应用程序运行时将创建新的应用程序域 (application domain)。同一台计算机上可能会同时运行着同一个应用程序的若干个实例此时每一个实例都拥有各自的应用程序域。

应用程序域通过作为应用程序状态的容器使应用程序得以隔离。应用程序域作为应用程序中和它使用的类库中所定义的类型的容器和边界。同一个类型若被加载到不同的应用程序域中就成为各自独立的客体,由它们在各自应用程序域中产生的实例亦不可直接共享。例如,对于这些类型的静态变量,每个应用程序域都有自己的副本,并且这些类型的静态构造函数在每个应用程序域中也要(最多)运行一次。关于如何处理程序域的创建和销毁,各实现可以按具体情况确定自己的策略或机制。

当执行环境调用指定的方法称为应用程序的入口点时发生应用程序启动 (application startup)。此入口点方法总是被命名为 Main,可以具有下列签名之一:

static void Main() {...}

static void Main(string[] args) {...}

static int Main() {...}

static int Main(string[] args) {...}

如上所示入口点可以选择返回一个 int 值。此返回值用于应用程序终止(第 3.2 节)。

入口点可以包含一个形参可选。该参数可以具有任意名称但参数的类型必须为 string[]。如果存在形参,执行环境会创建并传递一个包含命令行参数的 string[] 实参,这些命令行参数是在启动应用程序时指定的。string[] 参数永远不能为 null,但如果没有指定命令行参数,它的长度可以为零。

由于 C# 支持方法重载因此类或结构可以包含某个方法的多个定义前提是每个定义有不同的签名。但在一个程序内,没有任何类或结构可以包含一个以上的名为 Main 的方法,因为 Main 的定义限定它只能被用作应用程序的入口点。允许使用 Main 的其他重载版本,前提是它们具有一个以上的参数,或者它们的唯一参数的类型不是 string[]

应用程序可由多个类或结构组成。在这些类或结构中可能会有若干个拥有自己的 Main 方法因为 Main 的定义限定它只能被用作应用程序的入口点。这样的情况下,必须利用某种外部机制(如命令行编译器的选项)来选择其中一个 Main 方法用作入口点。

C# 每个方法都必须定义为类或结构的成员。通常,方法的已声明可访问性(第 3.5.1 节)由其声明中指定的访问修饰符(第 10.2.3 节)确定。同样,类型的已声明可访问性由其声明中指定的访问修饰符确定。为了使给定类型的给定方法可以被调用,类型和成员都必须是可访问的。然而,应用程序入口点是一种特殊情况。具体而言,执行环境可以访问应用程序的入口点,无论它本身的可访问性和封闭它的类型的可访问性是如何在声明语句中设置的。

在所有其他方面入口点方法的行为与非入口点方法类似。

1.2 应用程序终止

应用程序终止 (application termination) 将控制返回给执行环境。

如果应用程序的入口点 (entry point) 方法的返回类型为 int则返回的值用作应用程序的终止状态代码 (termination status code)。此代码的用途是允许与执行环境进行关于应用程序运行状态成功或失败的通信。

如果入口点方法的返回类型为 void那么到达了终止该方法的右大括号 (})或者执行不带表达式的 return 语句将产生终止状态代码 0

在应用程序终止之前将调用其中还没有被垃圾回收的所有对象的析构函数除非这类清理功能已被设置为取消使用例如通过调用库方法 GC.SuppressFinalize

1.3 声明

C# 程序中的声明定义程序的构成元素。C# 程序是用命名空间(第 9 章)组织起来的,一个命名空间可以包含类型声明和嵌套的命名空间声明。类型声明(第 9.5 节)用于定义类(第 10 节)、结构(第 11 节)、接口(第 13 节)、枚举(第 14 节)和委托(第 15 节)。在一个类型声明中可以使用哪些类型作为其成员,取决于该类型声明的形式。例如,类声明可以包含常量声明(第 10.3 节)、字段声明(第 10.4 节)、方法声明(第 10.5 节)、属性声明(第 10.6 节)、事件声明(第 10.7 节)、索引器声明(第 10.8 节)、运算符声明(第 10.9 节)、实例构造函数声明(第 10.10 节)、静态构造函数声明(第 10.11 节)、析构函数声明(第 10.12 节)和嵌套的类型声明。

一个声明在它自已所属的那个声明空间 (declaration space) 中定义一个名称。除非是重载成员(第
3.6 节),否则,在同一个声明空间下若有两个以上的声明语句声明了具有相同名称的成员,就会产生编译时错误。同一个声明空间内绝不能包含不同类型的同名成员。例如,声明空间绝不能包含同名的字段和方法。

有若干种不同类型的声明空间如下所述。

·         在程序的所有源文件中一个 namespace-member-declaration 若没有被置于任何一个 namespace-declaration 它就属于一个称为全局声明空间 (global declaration space) 的组合声明空间。

·         在程序的所有源文件中一个 namespace-member-declaration 若在 namespace-declaration 中具有相同的完全限定的命名空间名称它就属于一个组合声明空间。

·         每个类、结构或接口声明创建一个新的声明空间。新的声明空间名称是通过 class-member-declarationstruct-member-declaration interface-member-declaration 引入的。除了重载实例构造函数声明和静态构造函数声明外类或结构成员声明不能引入与该类或结构同名的成员。类、结构或接口允许声明重载方法和索引器。另外,类或结构允许重载实例构造函数和运算符的声明。例如,类、结构或接口可以包含多个同名的方法声明,前提是这些方法声明的签名(第 3.6 节)不同。注意,基类与类的声明空间无关,基接口与接口的声明空间无关。因此,允许在派生类或接口内声明与所继承的成员同名的成员。我们说这类成员隐藏 (hide) 了那些被它们所继承的成员。

·         每个枚举声明创建一个新的声明空间。名称通过 enum-member-declarations 引入此声明空间。

·         每个 block  switch-block以及 forforeach using 语句都会为局部变量和局部常量创建一个声明空间名为局部变量声明空间 (local variable declaration space)。名称通过 local-variable-declaration local-constant-declaration 引入此声明空间。如果块是实例构造函数、方法或运算符声明的体,或是索引器声明的 get set 访问器,这些声明中声明的参数是块的局部变量声明空间的成员。如果局部变量声明空间的两个成员具有相同的名称则会发生错误。如果某个块的局部变量声明空间和嵌套的某个局部变量声明空间包含具有相同名称的元素,则会发生错误。因此,在嵌套声明空间中不可能声明与封闭它的声明空间中的局部变量或常量同名的局部变量或常量。只要两个声明空间彼此互不包含则两个声明空间可以包含同名的元素。

·         每个 block switch-block 都为标签创建一个单独的声明空间。名称通过 labeled-statement 引入此声明空间通过 goto-statement 语句被引用。块的标签声明空间 (label declaration space) 包含任何嵌套块。因此在嵌套块中不可能声明与封闭它的块中的标签同名的标签。

声明名称的文本顺序通常不重要。具体而言,声明和使用命名空间、常量、方法、属性、事件、索引器、运算符、实例构造函数、析构函数、静态构造函数和类型时,文本顺序并不重要。在下列情况下声明顺序非常重要:

·         字段声明和局部变量声明的声明顺序确定其初始值设定项如果有的执行顺序。

·         在使用局部变量前必须先定义它们 3.7

·         当省略 constant-expression 值时枚举成员声明 14.3 的声明顺序非常重要。

命名空间的声明空间是开放式的”,两个具有相同的完全限定名的命名空间声明提供相同的声明空间。例如

namespace Megacorp.Data
{
class Customer
{
     ...
}
}

namespace Megacorp.Data
{
class Order
{
     ...
}
}

以上两个命名空间声明提供相同的声明空间在本示例中声明两个具有完全限定名 Megacorp.Data.Customer Megacorp.Data.Order 的类。由于两个声明共同构成同一个声明空间因此如果每个声明中都包含一个同名类的声明则将导致编译时错误。

正如上面所述块的声明空间包括所有嵌套块。因此,在下面的示例中,FG 方法导致编译时错误,因为名称 i 是在外部块中声明的,不能在内部块中重新声明。但方法

【上篇】
【下篇】

抱歉!评论已关闭.