
擁有進入點(entry point)的程序集稱應用程序(application)。當運行一應用程序時,將創建一新應用程序域(application domain)。同一個應用程序可在同一臺機器(machine)上同時運行多個實例,并且每個實例都有自己的應用程序域。
應用程序域作為應用程序狀態(application state)之容器(container),使應用程序相互隔離(isolation)。應用程序域是定義于應用及所用類庫的類型之容器與邊界。加載入不同的應用程序域的同一類型是相互涇渭分明的,而其實例化的對象也不會在應用程序域之間直接共享。比方說,對于這些類型的靜態變量,每個應用程序域都自有一份其副本,同時這些類型的靜態構造函數在應用程序域中至多運行一次。實現可以自由為應用程序域的創建和銷毀提供指定實現(implementation-specific)策略或機制。
應用程序啟動(Application startup)時,執行環境會調用一個特指的方法作為應用程序的進入點(entry point)。入口點方法一貫稱為 Main,且可為下列簽名中的一種:
static void Main() {...}static void Main(string[] args) {...}static int Main() {...}static int Main(string[] args) {...}如上所示,進入點可以選擇 int 為其返回值。這個返回值通常被用在應用程序終止(application termination,第三章第二節)時。
進入點有個可選形參。這個參數可以用任何名稱,但它的類型必須是 string[]。如果出現形參,那么當應用程序啟動時,執行環境將通過命令行參數(command-line arguments)的方式創建并傳遞指定的 string[] 實參。實參 string[] 永不為空(null),但它可能長度為零(如果命令行沒有指定實參的話)。
由于 C# 支持方法重構(overload),類或結構可以包含一個方法的多個定義,前提是每個重載版本都有不同的方法簽名。然而,在一個程序內,類或結構內不能同時存在多個叫做 Main 的方法,因為 Main 被限定為只能作為應用程序的入口點。如果提供超過一個參數或者唯一參數類型不是 string[],則允許重載多個 Main 版本。
應用程序可由多個類與結構組成,也許會有多個 Main 方法在這些類或結構內,由于 Main 的定義限定它只能是應用程序入口點,所以在這種情況下,外部機制(諸如命令行編譯器選項)必須從中選擇其一作為應用程序的進入點。
在 C# 中每一個方法都必須定義為類或結構的成員,一般情況下方法的聲明可訪問性(declared accessibility,第三章第 5.1 節)是由訪問控制修飾符(access modifiers,第十章第 3.5 節)所決定的;同樣,類型的聲明聲明可訪問性也是由其訪問控制修飾符所決定的。為了調用所給定類型的給定方法,類型與成員都必須可被訪問(accessible),然應用程序進入點是特例。不管應用程序進入點的聲明可訪問性及其閉包類型的聲明可訪問性,執行環境總能訪問到它們。
應用程序進入點方法(entry point method)不能放入泛型類聲明內。
在其它各方面,進入點方法與非進入點方法的行為類似。
應用程序終止將返回控制權給執行環境。
應用程序進入點方法的返回類型是 int,該值作為應用程序終止狀態代碼(application's termination status code)返回。該代碼的目的是允許與執行環境通訊以告知成功或失敗。
如果進入點方法的返回類型是 void,遇到該方法的關門大括號 } 或執行到一個沒有表達式的返回語句(return statement),則終止狀態代碼為 0。
先于應用程序的終止,未被垃圾回收的對象的析構函數將被調用,除非這類清理工作已被取消(supPRessed)(比方說通過調用庫方法GC.SuppressFinalize)。
C# 程序中的聲明定義了程序的組成元素。C# 程序有系統地使用了命名空間(namespace,第九章),命名空間可以包含類型聲明(type declarations)和嵌套命名空間聲明(nested namespace declarations)。類型聲明(type declarations,第九章第六節)用于定義類(class,第十章)、結構(struct,第十章第十四節)、接口(interface,第十三章)、枚舉(enum,第十四章)以及委托(delegates,第十五章)。類型聲明中允許的成員種類取決于類型聲明的形式。比方說類聲明可以包含聲明常量(constants,第十章第四節)、字段(fields,第十章第五節)、方法(methods,第十章第六節)、屬性(properties,第十章第七節)、事件(events,第十章第八節)、索引器(indexers,第十章第九節)、操作符(Operators,第十章第十節)、實例構造函數(instance constructors,第十章第十一節)、靜態構造函數(static constructors,第十章第十二節)、析構函數(destructors,第十章第十三節)和嵌套類型(nested types,第十章第 3.8 節)。
聲明在其所屬聲明空間(declaration space)內定義一個名稱。除重載成員(第三章第六節)外,同一聲明空間(declaration space)內出現兩個以上同名成員會引發「編譯時錯誤(compile-time error)」。同一聲明空不可同時包含不同類型的同名方法。比方說,聲明空間絕無包含同名字段與方法之可能。
有數種不同的聲明空間,其具體描述如下:
namespace-declaration 內的 namespace-member-declarations 是屬于一個叫做全局聲明空間(global declaration space)的組合聲明空間內的成員;namespace-declarations 內的 namespace-member-declarations 若擁有相同的完全限定命名空間名,則其屬于同一個組合聲明空間內;class-member-declarations、struct-member-declarations、interface-member-declarations 或 type-parameters 引入此聲明空間。除了重載實例構造函數和靜態構造函數,類或結構不允許聲明包含一個與其類名或結構名同名的成員。類、結構或結構允許重載聲明方法和索引器。此外類或結構允許重載聲明實例構造函數與操作符。比方說類、結構或接口可以包含多個聲明為同名的方法,這些所聲明的方法擁有不同的簽名(signature,第三章第六節)。注意,基類并不在該類的聲明空間內,基接口也不在該接口的聲明空間內,所以派生類或接口允許聲明一個與繼承成員同名的成員。這類成員隱藏(hide)了它們繼續的那些成員;fixed-parameters 與 parameter-arrays 以及 type-parameters 引入這個聲明空間;enum-member-declarations 引入這個聲明空間;fixed-parameters 和 parameter-arrays 以及 type-parameters 引入這個聲明空間。如果有函數成員或匿名函數成員的函數體,則將會被是為嵌套于局部變量聲明空間內。局部變量聲明控件和嵌套局部變量聲明空間內包含同名元素將引發錯誤。因此在一個閉包聲明空間內,如果包含嵌套聲明空間的話,那么不能在其內部聲明一個與閉包聲明空間內變量或常量同名的局部變量或常量。只有一種可能使得兩個聲明空間內包含同名元素,那就是這兩個聲明空間彼此不相互包含。block 或 switch-block,以及 for、foreach 和 using 語句將為局部變量和局部常量創建局部變量聲明空間。名稱將通過 local-variable-declarations 和 local-constant-declarations 引入這個聲明空間。注意,作為函數成員主體或匿名函數主體的塊,或是位于函數成員主體或匿名函數主體內的塊,將嵌套在本地變量聲明空間內(這個本地變量聲明空間是為其參數所聲明的)。因此,如果某個方法的局部變量和參數同名,那么將引發一個錯誤。block 或 switch-block 為每個標簽(label)創建相互隔離的聲明空間。名稱將通過 labeled-statements 引入該聲明空間,并通過 goto-statements 來引用。塊的標簽聲明空間(label declaration space)可包含任何嵌套塊。因此在嵌套塊內不能聲明一個與其所在閉包塊(enclosing block)標簽同名的標簽。聲明名稱的文本順序一般而言是不重要的(no significance)。具體而言,聲明并使用命名空間、常量、方法、屬性、事件、索引器、操作符、實例構造函數、析構函數、靜態構造函數以及類型,其文本順序并不重要。在以下情況下聲明順序比較重要:
when constant-expression 被省略時,枚舉成員聲明(第十四章第三節)的順序是重要的。命名空間的聲明空間是開放的(open ended),兩個相同完全限定名(fully qualified name)的命名空間擁有同一個聲明空間。比方說:
namespace Megacorp.Data{ class Customer { ... }}namespace Megacorp.Data{ class Order { ... }}這兩個命名空間位于同一個聲明空間內,在此例中兩個類的完全限定名分別是 Megacorp.Data.Customer 和 Megacorp.Data.Order。因為這兩個聲明位于同一個聲明空間內,所以如果這兩個類的完全限定名是一樣的話,會引發一個「編譯時錯誤」。
如上文所指定,塊(block)的聲明空間可以嵌套任意塊。因此,在下例中,F 方法和 G 方法會引發「編譯時錯誤」,因為外部塊中聲明了 i,那么內部塊就不能重復聲明(redeclared)。然而 H 方法和 I 方法是合法的,這是由于兩個 i 的聲明都位于相互獨立的非嵌套塊(separate non-nested blocks)內。
class A{ void F() { int i = 0; if (true) { int i = 1; } } void G() { if (true) { int i = 0; } int i = 1; } void H() { if (true) { int i = 0; } if (true) { int i = 1; } } void I() { for (int i = 0; i < 10; i++) H(); for (int i = 0; i < 10; i++) H(); }}命名空間和類型都擁有成員。在實體開始被引用時,實體成員一般都可通過限定名稱(qualified name)引入其中,通過標記(token). 引出成員的名字。
類型的成員既可在類型聲明中聲明,也可從其基類中繼承。當一個類型繼承自其基類時,所有基類成員(除了實例構造函數、析構函數以及靜態構造函數)都將成為派生類型的成員。基類成員的聲明可訪問性并不控制成員是否可被繼承——繼承可拓展到除實例構造函數、析構函數和靜態構造函數之外的任意成員。然而。也有可能派生類型無法訪問到所繼承的成員,比方說因為其聲明可訪問性(第三章第 5.1 節)或是因為其通過類型自身聲明隱藏(第三章第 7.1.2 節)。
如果命名空間與類型沒有閉包于一個命名空間,則它們將是全局命名空間(global namespace)的成員。這相當于名字直接在全局聲明空間內聲明了。
如果命名空間與類型在一個命名空間內,那么命名空間和類型將是這個外部命名空間的成員。這意味著名字直接在這個命名空間的聲明空間內聲明了。
命名空間沒有訪問限制(access restrictions)。不可以為命名空間聲明為 private、 protected 或 internal,命名空間永遠是可公開取得的(publicly accessible)。
結構成員是結構內聲明的成員,以及直接繼承自結構基類 System.ValueType 以及間接繼承自基類 object 的成員。
簡單類型的成員通過類型別名(alias)直接對應結構類型的成員:
sbyte 的成員是 System.SByte 結構的成員;byte 的成員是 System.Byte 結構的成員;short 的成員是 System.Int16 結構的成員;ushort 的成員是 System.UInt16 結構的成員;int 的成員是 System.Int32 結構的成員;uint 的成員是 System.UInt32 結構的成員;long 的成員是 System.Int64 結構的成員;ulong 的成員是 System.UInt64 結構的成員;char 的成員是 System.Char 結構的成員;float 的成員是 System.Single 結構的成員;double 的成員是 System.Double 結構的成員;decimal 的成員是 System.Deci
新聞熱點
疑難解答