隱含類型區域變數 (C# 程式設計手冊)
您可以宣告區域變數而不提供明確類型。 var
關鍵字會指示編譯器從初始化陳述式右側的運算式推斷變數的類型。 推斷型別可能是內建型別、匿名型別、使用者定義型別,或 .NET 類別庫中定義的型別。 如需如何使用 var
初始化陣列的詳細資訊,請參閱隱含型別陣列。
下列範例顯示可以使用 var
宣告區域變數的各種方法:
// i is compiled as an int
var i = 5;
// s is compiled as a string
var s = "Hello";
// a is compiled as int[]
var a = new[] { 0, 1, 2 };
// expr is compiled as IEnumerable<Customer>
// or perhaps IQueryable<Customer>
var expr =
from c in customers
where c.City == "London"
select c;
// anon is compiled as an anonymous type
var anon = new { Name = "Terry", Age = 34 };
// list is compiled as List<int>
var list = new List<int>();
請務必了解 var
關鍵字不代表 "variant",也不代表變數是不嚴格規定類型或晚期繫結的。 只代表編譯器會判斷並指派最適當的類型。
var
關鍵字可在下列內容中使用:
在區域變數 (方法範圍中宣告的變數) 上,如前述範例所示。
在 for 初始化陳述式中。
for (var x = 1; x < 10; x++)
在 foreach 初始化陳述式中。
foreach (var item in list) {...}
在 using 陳述式中。
using (var file = new StreamReader("C:\\myfile.txt")) {...}
如需詳細資訊,請參閱如何在查詢運算式中使用隱含型別區域變數和陣列。
var 和匿名型別
在許多情況下,使用 var
是選擇性的,只是為了在語法上便於使用。 不過,當變數以匿名型別初始化時,如果您稍後需要存取物件的屬性,則必須宣告該變數為 var
。 這是 LINQ 查詢運算式中的常見案例。 如需詳細資訊,請參閱匿名型別。
從原始程式碼的觀點來看,匿名型別沒有名稱。 因此,如果已使用 var
初始化查詢變數,則存取傳回的物件序列中屬性的唯一方法,就是使用 var
作為 foreach
陳述式中反覆運算變數的類型。
class ImplicitlyTypedLocals2
{
static void Main()
{
string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };
// If a query produces a sequence of anonymous types,
// then use var in the foreach statement to access the properties.
var upperLowerWords =
from w in words
select new { Upper = w.ToUpper(), Lower = w.ToLower() };
// Execute the query
foreach (var ul in upperLowerWords)
{
Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
}
}
}
/* Outputs:
Uppercase: APPLE, Lowercase: apple
Uppercase: BLUEBERRY, Lowercase: blueberry
Uppercase: CHERRY, Lowercase: cherry
*/
備註
下列限制適用於隱含型別變數宣告:
var
只能在區域變數於相同的陳述式中宣告和初始化時使用;此變數無法初始化為 null、方法群組或匿名函式。var
無法在類別範圍的欄位中使用。使用
var
宣告的變數無法在初始化運算式中使用。 換句話說,此運算式是合法的:int i = (i = 20);
,但此運算式會產生編譯時期錯誤︰var i = (i = 20);
無法在相同的陳述式中初始化多個隱含型別變數。
如果名為
var
的類型在範圍之內,則var
關鍵字會解析成該類型名稱,而且不會視為隱含型別區域變數宣告的一部分。
使用 var
關鍵字的隱含類型只能套用至本機方法範圍的變數。 隱含類型不適用於類別欄位,因為 C# 編譯器會在處理程式碼時發生邏輯矛盾:編譯器需要了解欄位的類型,但是它無法在分析指派運算式之前判斷類型,而運算式無法在不了解類型的情況下進行評估。 請考慮下列程式碼:
private var bookTitles;
bookTitles
是類型為 var
的類別欄位。 因為欄位沒有能評估的運算式,所以編譯器無法推斷 bookTitles
的類型為何。 此外,將運算式新增至欄位 (如同你對區域變數進行的操作) 也不足夠:
private var bookTitles = new List<string>();
當編譯器在編譯程式碼期間遇到欄位時,它會記錄每個欄位的類型,再處理任何與其建立關聯的運算式。 編譯器會在嘗試剖析 bookTitles
時發生相同的矛盾:它需要了解欄位的類型,但是編譯器通常會透過分析運算式來判斷 var
的類型,而這無法在不事先了解類型的情況下進行。
您會發現在難以判斷查詢運算式中查詢變數的確切建構類型時,var
也相當有用。 這會在群組與排序作業時發生。
當您不想要老是在鍵盤上鍵入變數的特定類型,或是此特定類型很明顯或不會增加程式碼的可讀性時,var
關鍵字也相當有用。 var
有用的其中一個範例是用於巢狀泛型型別時,例如用於群組作業的類型。 在下列查詢中,查詢變數的類型是 IEnumerable<IGrouping<string, Student>>
。 只要您及維護程式碼的其他使用者了解這點,為求便利和簡潔而使用隱含型別就不會有問題。
// Same as previous example except we use the entire last name as a key.
// Query variable is an IEnumerable<IGrouping<string, Student>>
var studentQuery3 =
from student in students
group student by student.Last;
使用 var
有助於簡化您的程式碼,但其使用應受限於需要的情況,或讓您的程式碼更容易讀取的情況。 如需有關使用 var
屬性正確時機的詳細資訊,請參閱《C# 程式碼撰寫指導方針》一文中的隱含型別區域變數一節。