隨著C#的發展,該語言內容不斷豐富,開發變得更加方便快捷,C# 的鋒利盡顯無疑。C# 語言從誕生起就是強型別語言,這一性質到今天不曾改變,我想以後也不會變。既然是強型別語言,那編寫任一程式均要求滿足下面的基本條件:
1、變數聲明必須指明其類型
2、變數類型明確後,其類型在Runtime亦不能改變
代碼如下:
public class Student { public string Name { get; set; } public int Age { get; set; } public string Like { get; set; } }
static void Main(string[] args){ int a = 10; string s = "abc"; Student student = new Student(); //下面出現編譯錯誤,變數類型在聲明後無法再變更 s = a; student = s; a = 10.1f;}
然而,在實際開發中我們經常面臨如下幾種常見問題:
1、在一個較大的程式程式中,只有一處或很少幾處(不超過3處)需要用到 某個或某些類型(如上 Student),其他地方不再需要這些類型。單獨聲明一個Student類型,所需代碼量,可能超過使用該類型時的代碼量,投入產出比不划算。
2、在一處程式中,只需要某種類型對象的部分屬性或方法參與運算。在這種情況下將該類型對象臨時轉換為程式所需的部分屬性和方法的對象,可使程式更加精簡。
3、其他情況........我暫未留意到......歡迎補充........
上面這些 C# 實際開發中常見問題,在 JavaScript 開發中有著比較好的解決方案,如下:
//在此處js中需要類比一個學生對象student = {"name":"張三","age":20,"like":"LOL"};//在此處js中需要類比一個老師對象teacher = {"name":"李老師","like":"沒收學生手機,自己LOL"};//此處需要將學生student轉換成只有name和age的對象person = {"name":student.name,"age":student.age};
如果你不熟悉上面的js文法,你可以去百度搜尋 “json文法”,告訴你很簡單哦(而且很重要)。
匿名對象(匿名型別)
因此C#在3.0版本中吸收了JavaScript指令碼語言的這種文法優點,對C#做了相應升級使其也支援這種文法形式(C#依然是強型別語言)。範例程式碼如下:
static void Main(string[] args){ new {Name="張三",Age=20,Like="LOL"};}
上面的C#代碼 通過new關鍵字告訴編譯器要建立一個對象,該對象具有Name,Age,Like三個屬性,=後為屬性對應的值。如此我們避開了“建立一個對象首先要有該物件類型的約束”,因此在開發過程中對於使用較少的類型我們無需再建立單獨的類了,上面提到的問題1被解決。
現在建立出來的對象沒指定具體類型,因此稱為匿名對象。
Var登場
現在要使用匿名對象,則需要使用變數引用它。雖然我們在建立時沒有指定對象的類型,但編譯器會在編譯過程中幫我們建立一個具有相關屬性和方法的類型。此時編譯出的類型名稱是隨機產生的,因此變數類型無法確定。樣本如下:
static void Main(string[] args){ //XXX為型別宣告 //x為引用變數 XXX x = new {Name="張三",Age=20,Like="LOL"};}
雖然我們不知道編譯器產生的類型名稱,但我們可 讓編譯器自己根據編譯的結果來推斷變數類型。此時var關鍵字便發揮作用了:
static void Main(string[] args){ var x = new {Name="張三",Age=20,Like="LOL"};}
var 關鍵字說明 x 的類型由賦於的值來決定(推定),並能根據編譯器推定給出智能提示,如:
var使用注意事項:
1、var 僅能聲明方法內的局部變數
2、var 聲明的變數在被賦值後類型即確定下了,後續程式中不能在賦其他類型的值
3、var x = new object() 沒有意義,不要寫這樣的代碼...............
現在有匿名對象和var推斷類型的支援,我們就能處理上面提到的問題2。範例程式碼如下:
static void Main(string[] args) { var x = new { Name = "張三", Age = 20, Like = "LOL" }; var s = new { Name = x.Name, Age = x.Age }; }
上面僅為樣本,如果你熟悉Linq或Entity Framework,那問題2對應的用法將是鋪天蓋地的.......
動態類型 dynamic 出場
對於匿名型別的使用一般局限於方法的局部,可理解為:隨用隨定義,用完就消失。有如下情況應該怎麼辦?
static void Main(string[] args) { var x = GetObject(); } private static XXX GetObject() { return new { Name = "張三", Age = 20, Like = "LOL" }; }
通過GetObject方法返回一個匿名對象,所以方法傳回值 類型名稱無法確定,此處暫時用XXX代替。在這種情況下返回的類型不確定,可以使用 dynamic 來指明。如下:
Main( x = { Name = , Age = , Like =
此時方法不會出現語法錯誤,程式可以成功編譯並執行。那麼 dynamic 到底做了什麼,可以使上面的程式成功編譯呢?
dynamic的作用:
1、dynamic 表示動態類型,動態類型的含義就是 程式編寫、編譯階段 類型不確定,在Runtime時再通過反射機制確定相關對象的屬性或方法。因此編寫階段不會進行文法檢測。
2、dynamic 可用來聲明 欄位、屬性、方法參數、方法傳回值
3、dynamic 不支援智能提示,因為你寫代碼時 dynamic 是什麼沒法知曉(反射)
dynamic 聲明的變數,可理解為 object 類型變數。所以給dynamic變數賦任何類型值都正確,但在使用變數來取得某個屬性值或調用某方法時(此時程式肯定處於Runtime狀態),CLR會檢查(反射)所調用的屬性或方法是否存在,不存在報運行時異常。
dynamic在 Asp.net Mvc web開發中處處使用,雖然看上去很複雜,本質就上面所說內容。
說明:
var 和 dynamic 看似功能類似,但它們是不同的:
|
var |
dynamic |
聲明欄位 |
× |
√ |
局部變數 |
√ |
√ |
方法參數類型 |
× |
√ |
方法傳回值類型 |
× |
√ |