出處:http://huan-lin.blogspot.com/2009/01/implicit-type-declaration-in-c-30.html
C# 3.0 增加了 var 關鍵字,你可以用它來宣告隱含型別,例如:
int i = 10;
var j = 10;
這兩行的作用完全相同,連編譯出來的 IL code 也都一個模樣:
.locals init (
[0] int32 i,
[1] int32 j)
L_0001: ldc.i4.s 10
L_0003: stloc.0
L_0004: ldc.i4.s 10
L_0006: stloc.1
因為 var 變數其實是靜態繫結的變數,亦即編譯時期就已經決定變數型別了。
那麼編譯器如何決定型別?透過你指定給變數的初始值來推測。
因此,使用 var 變數有個基本前提:一定要給初始值。
否則編譯時會出現錯誤:Implicitly-typed local variables must be initialized。
再看一個 var 的範例:
var numbers = new[] { 10, 20, 30, 40 };
foreach (var x in numbers)
{
Console.WriteLine(x);
}
編譯器將會推測 numbers 的型別為整數陣列(int32[]),迴圈計數值 x 則為 int32。
注意在建立此整數陣列時,使用的語法是 new[] 而不是一般的 new[int]。
此外,使用 var 宣告陣列時,陣列的所有元素都必須是同一型別,
否則編譯器無法決定該用甚麼型別。因此,下面這行寫法將無法通過編譯:
var mixedAry = new[] { 10, "abc" };
// Error! 編譯器無法決定該用什麼型別.
其他限制
除了必須給定初始值,var 還有下列限制:
- 只能用在區域變數。函式的參數也不能宣告為 var。
- 每一個 var 宣告只能有一個變數,所以你不能這樣寫:
var i = 10, j = 20; // 編譯錯誤:Implicitly typed locals cannot have multiple declarators.
- 如果你在同一塊命名空間裡面定義了一個名為 var 的類別,那麼編譯器會優先使用你定義的類別名稱,亦即在此命名空間內,程式碼當中的 var 都被視為類別,而非 var 關鍵字。
何時使用 var?
既然是編譯時期就已經決定型別,為什麼我們寫程式時不明白指定型別,
而要用 var 呢?
一個常見的理由是:可以少打一些字。特別是當變數型別比較長的情況,例如:
LinkedList emp1 = new LinkedList();
var emp2 = new LinkedList();
其中 emp2 的宣告就簡潔許多,對程式的可讀性也沒有太大的影響,因為你從初始化的程式碼就能知道 emp2 的型別。再看一個使用 LINQ 的例子:
string[] fruits = { "apple", "banana", "mango" };
var items =
from s in fruits
where s.EndsWith("go")
select s;
foreach (var item in items)
{
Console.WriteLine(item);
}
這時候,item2 的型別是什麼呢?是 IEnumerable<string>。
對於熟悉 LINQ 的人來說,這種寫法應該不成問題,
但是不熟 LINQ 的人在看此範例時,可能會摸不著頭腦:到底 items 是什麼型別啊?
因此,何時該用 var 來宣告區域變數,對於每一種情況,各人看法可能不盡相同,
在選擇時不妨考慮一下是否會影響程式的可讀性。
所幸 var 只能用於區域變數,即使程式設計師不管三七二十一,
能用 var 的場合就用,其產生的副作用應該也不會太大。
但 有一種情況一定得用 var,就是當你使用匿名型別的時候。
甚麼叫匿名型別?
有時候,例如在某個函式裡面,我們會臨時需要一個簡單的類別來儲存一些簡單資料,
但又不想為了這個簡單的需求另外定義一個類別,
此時便可使用 C# 的匿名型別(anonymous type)。
留言