隱含類型區域變數 (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# 程式碼撰寫指導方針》一文中的隱含型別區域變數一節。

另請參閱