自學筆記這系列是我自己學習的一些心得分享,歡迎指教。這系列的分享,會以 C# + 我比較熟的 Net 3.5 環境為主。
另外本系列預計至少會切成【打地基】和【語法應用】兩大部分做分享。打地基的部分,講的是 LINQ 的組成元素,這部分幾乎和 LINQ 無關,反而是 C# 2.0、C# 3.0 的一堆語言特性,例如:型別推斷、擴充方法、泛型、委派等等,不過都會把分享的範圍限制在和 LINQ 應用有直接相關功能。
PS. LINQ 自學筆記幾乎所有範例,都可直接複製到 LINQPad 4 上執行。因為它輕巧好用,功能強大,寫範例很方便,請大家自行到以下網址下載最新的 LINQPad:http://www.LINQpad.net/。
區域型別推斷(Local Type Inference)從 VB 的角度講比較有趣,C# 就相對單純。細節之後會提到,現在先看一下「型別推斷」是什麼?
MSDN VB:Visual Basic 編譯器會使用「型別推斷」(Type Inference) 來判斷未使用 As 子句宣告之區域變數的資料型別。 編譯器是根據初始化運算式的型別推斷變數的型別。 這可以讓您宣告變數而不用明確陳述型別。
MSDN C#:可以給予區域變數推斷「型別」var,而非明確型別。 var 關鍵字會指示編譯器從初始化陳述式右側的運算式推斷變數的型別。 推斷的型別可能是內建型別、匿名型別、使用者定義型別,或 .NET Framework 類別程式庫中定義的型別。
PS. 在 C# 中,不使用「區域型別推斷」這個名詞,而是用「隱含型別區域變數(Implicitly Typed Local Variables)」,查詢關鍵字要下對喔!
換言之,在 VB 若定義一個區域變數同時賦予值,就可以省略型別宣告,讓編譯器在編譯時期決定變數的型別。這件事在 C# 也適用,只是把原本寫變數型別的地方改用 var 關鍵字即可。另外,因為編譯時期就會推斷出變數的型別,所以其實還是「強型別」的變數。
接著我們注意一個地方,上述定義文字中,都有特別強調一件事,就是【區域變數】!也就是說,型別推斷只適用於下述三種情況::
在實務上,常常會有一些新手開發人員會試圖把方法參數的型別用 var 來取代,但這是不可以的喔!方法參數並非區域變數。
但有趣的事情發生了,在 VB,方法參數我沒有定義型別,卻可以正常調用:
這也是我一開始說型別推斷從 VB 角度講比較有趣的原因,但現在還是先聚焦在型別推斷的使用上。我們先看下述範例,確定了解如何使用型別推斷功能(注意,LINQPad 預設 Statement 和 Expression 兩種撰寫模式之變數都是「區域變數」):
VB:
Dim n = 3
Dim s = "Hello"
Dim ary = New Integer() { 0, 1, 2 }
Dim myList = New List(Of Integer)
n.GetType().Dump()
s.GetType().Dump()
ary.GetType().Dump()
myList.GetType().Dump()
C#:
var i = 5;
var s = "Hello";
var a = new[] { 0, 1, 2 };
var list = new List<int>();
i.GetType().Dump();
s.GetType().Dump();
a.GetType().Dump();
list.GetType().Dump();
補充說明,Dump 這個方法,是 LINQPad 所提供的輸出方法,它有六種調用方式,文章末我會附上此方法六種簽名碼(signature),這裡我們先知道 Dump 方法等同於 Console.WriteLine 即可。
上面 VB 和 C# 的範例,我們可以發現定義區域變數時,都沒有宣告型別,但是最後輸出的型別卻是正確的,而且從 IntelliSense 也可以看到,表示 IDE 在我們撰寫程式時,就已經可以如同強型別一樣,推斷出變數型別,並提供該型別可用的方法、屬性、欄位:
到此,型別推斷這個語法特性其實已經大概講完了,應該也都清楚如何使用,下一篇我們再來談談,VB 使用型別推斷有趣而且要注意的地方,並說明上述 VB 的方法參數不定義型別卻可正確呼叫不會發生錯誤的原因。
-----------------LINQPad Dump 方法的簽名碼-----------------