官术网_书友最值得收藏!

1.2 C#語法基礎(chǔ)

成功編譯并運行HelloWorld程序之后,我們來分析代碼,了解它的各個組成部分。首先熟悉一下C#關(guān)鍵字以及可供開發(fā)者選擇的標識符。

初學者主題:關(guān)鍵字

為了幫助編譯器解釋代碼,C#中的某些單詞具有特殊地位和含義,它們稱為關(guān)鍵字。編譯器根據(jù)關(guān)鍵字的固有語法來解釋程序員寫的表達式。在HelloWorld程序中,class、static和void均是關(guān)鍵字。

編譯器根據(jù)關(guān)鍵字識別代碼的結(jié)構(gòu)與組織方式。由于編譯器對這些單詞有著嚴格的解釋,所以只能將關(guān)鍵字放在特定位置。如違反規(guī)則,編譯器會報錯。

1.2.1 C# 關(guān)鍵字

表1.1總結(jié)了C#關(guān)鍵字。

C# 1.0之后沒有引入任何新的保留關(guān)鍵字,但在后續(xù)版本中,一些構(gòu)造使用了上下文關(guān)鍵字,它們在特定位置才有意義,在其他位置則無意義[1]。這樣大多數(shù)C# 1.0代碼都能兼容后續(xù)版本[2]

1.2.2 標識符

和其他語言一樣,C#用標識符標識程序員編碼的構(gòu)造。在代碼清單1.1中,HelloWorld和Main均為標識符。分配標識符之后,以后將用它引用所標識的構(gòu)造。因此,開發(fā)者應(yīng)分配有意義的名稱,不要隨性而為。

好的程序員總能選擇簡潔而有意義的名稱,這使代碼更容易理解和重用。清晰和一致是如此重要,以至于“框架設(shè)計準則”(http://t.cn/RD6v4RB)建議不要在標識符中使用單詞縮寫[3],甚至不要使用不被廣泛接受的首字母縮寫詞。即使被廣泛接受(如HTML),使用時也要一致。不要一會兒這樣用,一會兒那樣用。為避免濫用,可限制所有首字母縮寫詞都必須包含到術(shù)語表中。總之,要選擇清晰(甚至是詳細)的名稱,尤其是在團隊中工作,或者開發(fā)要由別人使用的庫的時候。

標識符有兩種基本的大小寫風格。第一種風格被.NET框架創(chuàng)建者稱為Pascal大小寫(PascalCase),這是因為它曾經(jīng)在Pascal編程語言中很流行,它要求標識符的每個單詞首字母大寫,例如ComponentModel、Configuration和HttpFileCollection。注意在HttpFileCollection中,由于首字母縮寫詞HTTP的長度超過兩個字母,所以僅首字母大寫。第二種風格是camel大小寫(camelCase),除第一個字母小寫,其他約定一樣,例如quotient、firstName、httpFileCollection、ioStream和theDreadPirateRoberts。

表1.1 C#關(guān)鍵字

*這些是上下文關(guān)鍵字,括號中的數(shù)字(n)代表加入該上下文關(guān)鍵字的C#版本。

設(shè)計規(guī)范

·要更注重標識符的清晰而不是簡短。

·不要在標識符名稱中使用單詞縮寫。

·不要使用不被廣泛接受的首字母縮寫詞,對于那些已經(jīng)被廣泛接受的縮寫詞,在使用時也要保持一致。

下劃線雖然合法,但標識符一般不要包含下劃線、連字號或其他非字母/數(shù)字字符。此外,C#不像其前輩那樣使用匈牙利命名法(為名稱附加類型縮寫前綴)。這避免了數(shù)據(jù)類型改變時還要重命名變量,也避免了數(shù)據(jù)類型前綴經(jīng)常不一致的情況。

極少數(shù)情況下,有的標識符(比如Main)可能在C#語言中具有特殊含義。

設(shè)計規(guī)范

·要把兩個字母的首字母縮寫詞全部大寫,除非它是camelCase標識符的第一個單詞。

·包含三個或更多字母的首字母縮寫詞,僅第一個字母才要大寫,除非該縮寫詞是camelCase標識符的第一個單詞。

·在camelCase標識符開頭的首字母縮寫詞中,所有字母都不要大寫。

·不要使用匈牙利命名法(不要為變量名稱附加類型前綴)。

高級主題:關(guān)鍵字

雖然罕見,但關(guān)鍵字附加“@”前綴可作為標識符使用,例如可命名局部變量@return。類似地(雖不符合C#大小寫規(guī)范),也可將方法命名為@throw()并且跟隨一對括號,形如:@throw()。

在Microsoft的實現(xiàn)中,還有4個未文檔化的保留關(guān)鍵字:__arglist,__makeref,__reftype,__refvalue。它們僅在罕見的互操作情形下才需要使用,平時完全可以忽略。注意這4個特殊關(guān)鍵字以雙下劃線開頭。C#設(shè)計者保留將來把這種標識符轉(zhuǎn)化為關(guān)鍵字的權(quán)利。為安全起見,自己不要創(chuàng)建這樣的標識符。

1.2.3 類型定義

C#所有代碼都出現(xiàn)在一個類型定義的內(nèi)部,最常見的類型定義以關(guān)鍵字class開頭。如代碼清單1.3所示,類定義是class identifier {...}形式的代碼塊。

類型名稱(本例是HelloWorld)可以隨便取,但根據(jù)約定,它應(yīng)當使用PascalCase風格。就本例來說,可選擇的名稱包括Greetings、HelloInigoMontoya、Hello或者簡單地稱為Program。(對于包含Main()方法的類,Program是個很好的名稱。Main()方法的詳情稍后講述。)

代碼清單1.3 基本的類聲明

設(shè)計規(guī)范

·要用名詞或名詞短語命名類。

·要為所有類名使用PascalCase大小寫風格。

程序通常包含多個類型,每個類型包含多個方法。

1.2.4 Main方法

初學者主題:什么是方法?

語法上說,C#方法是已命名代碼塊,由一個方法聲明(例如static void Main())引入,后跟一對大括號({}),其中包含零條或多條語句。方法可執(zhí)行計算或操作。與書面語言中的段落相似,方法提供了結(jié)構(gòu)化和組織代碼的一種方式,使之更易讀。更重要的是,方法可以重用,可從多個地方調(diào)用,所以避免了代碼的重復。方法聲明除了引入方法并定義方法名,還要定義傳入和傳出方法的數(shù)據(jù)。在代碼清單1.4中,Main()連同后面的{...}便是C#方法的例子。

C#程序從Main方法開始執(zhí)行。該方法以static void Main()開頭。在命令控制臺中輸入dotnet run HelloWorld.exe執(zhí)行程序時,程序?qū)硬⒔馕鯩ain的位置,然后執(zhí)行其中第一條語句。如代碼清單1.4所示。

代碼清單1.4 HelloWorld分解示意圖

雖然Main方法聲明可進行某種程度的變化,但關(guān)鍵字static和方法名Main是始終都需要的。

高級主題:Main方法聲明

C#要求Main方法返回void或int,而且要么無參,要么接收一個字符串數(shù)組。代碼清單1.5展示了Main方法的完整聲明。

代碼清單1.5 帶有參數(shù)和返回類型的Main方法

args參數(shù)是用于接收命令行參數(shù)的字符串數(shù)組。但數(shù)組第一個元素不是程序名稱,而是可執(zhí)行文件名稱[4]后的第一個命令行參數(shù),這和C和C++不同。用System.Environment.CommandLine獲取執(zhí)行程序所用的完整命令。

Main返回的int是狀態(tài)碼,標識程序執(zhí)行是否成功。返回非零值通常意味著錯誤。

語言對比:C++/Java——main()

Main返回的int是狀態(tài)碼,標識程序執(zhí)行是否成功。返回非零值通常意味著錯誤。此外,從C#7.1開始,Main方法也支持async/await修飾詞。

注意 全部小寫問題

與C風格的“前輩”不同,C#的Main方法名使用大寫M,和C#的PascalCase命名約定一致。

將Main方法指定為static意味著這是“靜態(tài)”方法,可用類名.方法名的形式調(diào)用。若不指定static,用于啟動程序的命令控制臺還要先對類進行實例化,然后才能調(diào)用方法。第6章將用整節(jié)篇幅講述靜態(tài)成員。

Main()之前的void表明方法不返回任何數(shù)據(jù)(將在第2章進一步解釋)。

C#和C/C++一樣使用大括號封閉構(gòu)造(比如類或者方法)的主體。例如,Main方法主體就是用大括號封閉起來的。本例方法主體僅一條語句。

1.2.5 語句和語句分隔符

Main方法只含一條語句,即System.Console.WriteLine();,它在控制臺上輸出一行文本。C#通常用分號標識語句結(jié)束。每條語句都由代碼要執(zhí)行的一個或多個行動構(gòu)成。聲明變量、控制程序流程或調(diào)用方法都是語句的例子。

語言對比:Visual Basic——基于行的語句

有的語言以行為基本單位,這意味著如果不加上特殊標記,語句便不能跨行。在Visual Basic 2010以前,Visual Basic一直是典型的基于行的語言。它要求在行末添加下劃線表示語句跨越多行。從Visual Basic 2010起,行連續(xù)符在大多情況下是可選的。

高級主題:無分號的語句

C#的許多編程元素都以分號結(jié)尾。不要求分號的一個例子是switch語句。由于大括號總是包含在switch語句中,所以C#不要求語句后跟分號。事實上,代碼塊本身就被視為語句(它們也由語句構(gòu)成),不要求以分號結(jié)尾。類似地,有的編程元素(比如using指令)雖然分號顯示為后綴但不被視為語句。

由于換行與否不影響語句的分隔,所以可將多條語句放到同一行,C#編譯器認為這一行包含多條指令。例如,代碼清單1.6在同一行包含了兩條語句。執(zhí)行時在控制臺窗口分兩行顯示Up和Down。

代碼清單1.6 一行上的多條語句

C#還允許一條語句跨越多行。同樣地,C#編譯器根據(jù)分號判斷語句結(jié)束位置。在代碼清單1.7中,HelloWorld程序里原本單行的WriteLine()代碼被分成多行書寫。

代碼清單1.7 一條語句跨越多行

1.2.6 空白

分號使C#編譯器能忽略代碼中的空白。除少數(shù)特殊情況,C#允許代碼隨意插入空白而不改變語義。在代碼清單1.6和代碼清單1.7中,在語句中或語句間換行,甚至不換行都可以,對編譯器最終創(chuàng)建的可執(zhí)行文件沒有任何影響。

初學者主題:什么是空白?

空白是一個或多個連續(xù)的格式字符(比如制表符、空格和換行符)。刪除單詞間的所有空白肯定會造成歧義,刪除引號字符串中的任何空白也會如此。

程序員經(jīng)常利用空白對代碼進行縮進來增強可讀性。來看看代碼清單1.8和代碼清單1.9展示的兩個版本的HelloWorld程序。

代碼清單1.8 不縮進

代碼清單1.9 刪除一切可以刪除的空白

雖然這兩個版本看起來和原始版本頗有不同,但C#編譯器認為所有版本無差別。

初學者主題:用空白格式化代碼

為增強可讀性,用空白對代碼進行縮進很有必要。寫代碼時要遵循制訂好的編碼標準和約定,以增強代碼的可讀性。

本書約定每個大括號都單獨占一行,并縮進大括號內(nèi)的代碼。如一對大括號嵌套了第二對大括號,第二對大括號中的代碼也縮進。

這不是強制性的C#標準,只是風格偏好。

[1] 例如在C# 2.0設(shè)計之初,語言設(shè)計者將yield指定成關(guān)鍵字。在Microsoft發(fā)布的C# 2.0編譯器的alpha版本中(該版本分發(fā)給了數(shù)千名開發(fā)者),yield以一個新關(guān)鍵字的身份存在。但語言設(shè)計者最終選擇使用yield return而非yield,從而避免將yield作為新關(guān)鍵字。除非與return連用,否則它沒有任何特殊意義。

[2] 偶爾也有不兼容的情況,比如C# 2.0要求為using語句提供的對象必須實現(xiàn)IDisposable接口,而不能只是實現(xiàn)Dispose()方法。還有一些少見的泛型表達式,比如F(G<A,B>(7))在C# 1.0中代表F((G<A),(B>7)),而在C# 2.0中代表調(diào)用泛型方法G<A,B>,傳遞實參7,結(jié)果傳給F。

[3] 有兩種單詞縮寫:一種是“Abbreviation”,比如Professor縮寫為Prof.;另一種是“Contraction”,比如Doctor縮寫為Dr。——譯者注

[4] 也就是程序名稱,比如HelloWorld.exe。——譯者注

主站蜘蛛池模板: 西畴县| 金昌市| 德钦县| 乐业县| 林芝县| 大庆市| 漳浦县| 班玛县| 澳门| 甘肃省| 蕲春县| 万源市| 泌阳县| 苍梧县| 鹤壁市| 沐川县| 黔东| 乐至县| 丰城市| 亳州市| 且末县| 绥江县| 青阳县| 凤冈县| 余江县| 齐齐哈尔市| 紫阳县| 平阴县| 仲巴县| 砀山县| 都江堰市| 响水县| 延吉市| 湾仔区| 如皋市| 苏州市| 东山县| 弋阳县| 清远市| 渝北区| 高州市|