1. 程式人生 > >解讀經典《C#高階程式設計》第七版 Page20-32.核心C#.Chapter2

解讀經典《C#高階程式設計》第七版 Page20-32.核心C#.Chapter2

前言

 

講到核心C#的語法,其實很難講,因為大部分是基礎知識。如果只講入門的基礎知識,那細節又多,意義也不大。我們就不講一般性的內容,而是找一些有趣的點,展開講講。

 

01

Hello World

 

Hello World

一般開始程式設計的開頭,都是寫一個Hello World程式,這本書也是不能免俗。我們發現,Hello World基本都是用控制檯(Console)程式寫的。為什麼是控制檯程式?控制檯程式只是一個測試用,學習用的框架嗎?並不是這樣。瞭解Java程式的同學可能都會發現,很多Java程式執行起來都是一個黑乎乎的控制檯程式,年代越早這種情況越普遍。現在比較少了,畢竟體驗不好,逐漸用UI或者系統Service代替。但控制檯還是很強大的,在Windows面世之前,所有的程式都是控制檯程式,比如用Foxpro開發的財務記賬系統。而現在這種控制檯程式也很多,Java方面更多,因為Java要跨平臺,就相對的重功能輕UI。現在做前端開發,標配都會有不少叫XXX-CLI的控制檯工具,用於生成腳手架程式碼。

程式入口

為什麼控制檯程式入口是Main()方法?我們知道,程式都需要入口,而不同型別的程式,入口都不同,比如控制檯、Winform程式是Main()方法,而asp.net程式是Application_Start()方法。

編譯器

Csc.exe是什麼?它是C#的命令列編譯器程式,我們可以將Visual Studio(以下簡稱VS)理解為就是集成了一大堆包括csc.exe這類控制檯程式而形成的一個大工具系統。類同Java,Java的編譯器程式是javac.exe,java編譯完成後的程式碼檔案是*.class檔案,執行*.class檔案需要另外一個控制檯程式java.exe,即用命令列執行java.exe xxx.class。而.Net有所不同,csc.exe編譯完成後是一個可執行的exe程式(或者類庫*.dll),微軟的Windows革了控制檯的命,所以我們用微軟的工具時天然的會感覺到去控制檯化,比如VS,體驗好到.Net程式設計師不願意去做Java開發。

Static

Main()方法為什麼是靜態的(static)?我們會發現,不管是Java,C#,Main方法都是靜態方法,這給初學者其實帶來一定的迷惑性。我想,不能說程式入口必須用靜態方法,因為“在位元世界裡,沒有程式碼實現不了的事情”,而是因為使用靜態方法是“最好的入口設計”。我們用物件化的人類語言來模擬程式的啟動,它應該是這樣描述:

程式.啟動();

用C#控制檯程式程式碼實現的就是:

Program.Main();

我們會發現,這樣一來Main()就應該是一個Program類的靜態方法。那為什麼不先var p = new Programm(),在呼叫p.Main()?因為程式啟動只應該是為了“啟動”,而不是為了new一個物件,new一個物件可能會帶來副作用,比如new一個物件會附帶著對物件的初始化,而物件的初始化又帶著一堆構造器程式碼,而這並不是程式“啟動”該做的事情。因此靜態的Main()方法是最好的設計。

 

02

變數

 

變數定義

C#的變數定義,使用前必須初始化。這是學Java的,為了程式的強壯性和安全性。 但同時,這句話是有前提的,是“方法中的變數,必須初始化後才能使用。”而類定義中的欄位呢?並不需要。為什麼??其實很簡單,我們設計一門語言,它的本質是工具,是為了方便開發者,而不是給開發者添堵來的。這句話作為第一性原理,可以應用到理解語言的方方面面。假如你設計了一個類,還要在類的構造方法裡逐個初始化類的所有欄位,你是不是要發瘋?所以類在new的時候,它的欄位會自動被賦予“型別的預設值”。比如int就是0,string就是null。取得一個型別的預設值,我們可以用比如:

var value = default(int);

這樣寫在實際開發中幾乎用不到,但等到我們後面再定義泛型類的時候,defalt(T),可能是必須用到的,用來取得一個型別的預設值。

而為什麼方法中的變數會必須有預設值呢?我想語言的設計者,應該是認為:“你寫一段程式碼,要定義一個變數,就應該是知道應該給變數初始化什麼值,才能使這段程式碼執行的最安全和保持健壯”。

型別推斷

C#定義變數時,可以讓編譯器進行型別推斷,而不明確宣告型別,比如:

var endDateTemp = endDate.Value.AddDays(1);

型別推斷var是個好東西。作為一個完美主義,我初學C#時,把握不好該不該用var?用var明顯不好的一點是,閱讀性不夠好,你不知道定義的這個型別是什麼型別,在VS中,你需要用滑鼠移到變數上,才能看到這個變數的型別是什麼。所以曾經有一段時間,我強烈的拒絕用var,變數定義型別必須手寫。然鵝我現在已經定義變數幾乎都用var了。因為要使用太多的類,在現代強型別開發的風潮之下,類的名稱又往往很長,手寫將大大影響開發效率。實際上,寫這麼多var,並沒有給我帶來之前我擔心的困擾,反而寫的很順,很爽。但作為完美主義的我,還是堅持在某些情況下,不使用var,因為我堅信:“任何好東西,都是不能濫用的”。所以,“在不影響開發效率的前提下,不使用var”,就是我的一直秉承的原則。我一般原則是:

  1. 如果接收一個方法的返回值,我一般用var
  2. 定義並new一個物件,我一般不用var;定義基礎型別和string,我基本不用var

變數作用域

作用域不詳述。不過我分享一個我使用花括號來避免變數作用域衝突的小技巧,有點意思。

常量 const

常量不詳述。不過有句話很有意思,“常量總是靜態的”,但這不僅僅是理解為定義常量時不需要使用static,而是它具有static變數定義的本質,就是“資料只有一份”。所以我們可以暢想一下,如果定義了一個類User,這個類中定義了一個int常量欄位,那麼不管這個類建立了1個還是100個,它們使用的這個常量始終只有一份,儲存在堆疊中。

 

下一篇,講預定義型別。

 

覺得文章有意義的話,請動動手指,分享給朋友一起來共同學習進步。

 

歡迎關注本人微信公眾號,更及時的關注最新文章(每週三篇原創文章,以及多篇專題文章):

附文:

C# 翻身?微軟重寫開源的 C# 編譯器!

C#中變數的作用域

 

上一篇:解讀經典-《C#高階程式設計》第七版-Chapter1-.Net體系結構-Page13-20