C#3.0新增功能03 隱式類型本地變量

從 Visual C# 3.0 開始,在方法範圍內聲明的變量能夠具備隱式「類型」var。 隱式類型本地變量爲強類型,就像用戶已經自行聲明該類型,但編譯器決定類型同樣。 i 的如下兩個聲明在功能上是等效的:
var i = 10; // 隱式類型
int i = 10; // 顯式類型

下面的示例演示兩個查詢表達式。 在第一個表達式中,var 的使用是容許的,但不是必需的,由於查詢結果的類型能夠明確表述爲 IEnumerable<string>。 不過,在第二個表達式中,var 容許結果是一系列匿名類型,且相應類型的名稱只可供編譯器自己訪問。 若是使用 var,便沒法爲結果新建類。 請注意,在示例 #2 中,foreach 迭代變量 item 必須也爲隱式類型。html

// 示例 #1: 當 select 子句指定字符串時,var是可選的
string[] words = { "apple", "strawberry", "grape", "peach", "banana" };
var wordQuery = from word in words
                where word[0] == 'g'
                select word;

// 由於序列中的每一個元素都是字符串,而不是匿名類型,因此var在這裏也是可選的。
foreach (string s in wordQuery)
{
    Console.WriteLine(s);
}

// 示例 #2: var 是必需的,由於select子句指定匿名類型
var custQuery = from cust in customers
                where cust.City == "Phoenix"
                select new { cust.Name, cust.Phone };

// 必須使用var,由於序列中的每一個項都是匿名類型
foreach (var item in custQuery)
{
    Console.WriteLine("Name={0}, Phone={1}", item.Name, item.Phone);
}
 
隱式類型本地變量

可聲明局部變量而無需提供顯式類型。 var 關鍵字指示編譯器經過初始化語句右側的表達式推斷變量的類型。 推斷類型能夠是內置類型、匿名類型、用戶定義類型或 .NET Framework 類庫中定義的類型。 有關如何使用 var 初始化數組的詳細信息,請參閱隱式類型化數組express

如下示例演示使用 var 聲明局部變量的各類方式:數組

// i 被編譯成 int 類型
var i = 5;

// s 被編譯成 string 類型
var s = "Hello";

// a 被編譯成 int[] 數組
var a = new[] { 0, 1, 2 };

// expr 被編譯成 IEnumerable<Customer> 或者 IQueryable<Customer> 類型
var expr =
    from c in customers
    where c.City == "London"
    select c;

// anon 被編譯成匿名類型
var anon = new { Name = "Terry", Age = 34 };

// list 被編譯成 List<int> 集合                            
var list = new List<int>();

重要的是瞭解 var 關鍵字並不意味着「變體」,而且並不指示變量是鬆散類型或是後期綁定。 它只表示由編譯器肯定並分配最適合的類型。app

在如下上下文中,可以使用 var 關鍵字:ide

  • 在局部變量(在方法範圍內聲明的變量)上,如前面的示例所示。函數

  • 在 for 初始化語句中ui

for(var x = 1; x < 10; x++)
foreach(var item in list){...}
using (var file = new StreamReader("C:\\myfile.txt")) {...}

有關詳細信息,請參閱如何:在查詢表達式中使用隱式類型本地變量和數組spa

var 和匿名類型

在許多狀況下,使用 var 是可選的,只是一種語法便利。 可是,在使用匿名類型初始化變量時,若是須要在之後訪問對象的屬性,則必須將變量聲明爲 var。 這是 LINQ 查詢表達式中的常見方案。 有關詳細信息,請參閱匿名類型code

從源代碼角度來看,匿名類型沒有名稱。 所以,若是使用 var 初始化了查詢變量,則訪問返回對象序列中的屬性的惟一方法是在 foreach 語句中將 var 用做迭代變量的類型。htm

class ImplicitlyTypedLocals2
{
    static void Main()
    {
        string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" };

        // 若是查詢生成一系列匿名類型,則在foreach語句中使用var訪問屬性。
        var upperLowerWords =
             from w in words
             select new { Upper = w.ToUpper(), Lower = w.ToLower() };

        // 執行查詢
        foreach (var ul in upperLowerWords)
        {
            Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower);
        }
    }
}
/* 輸出:
    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>>。 只要你和必須維護你的代碼的其餘人瞭解這一點,使用隱式類型化實現便利性和簡便性時便不會出現問題。

// 與前面的示例相同,只是咱們使用整個姓氏做爲鍵。
// 查詢變量是IEnumerable<igrouping<string,student>>
var studentQuery3 =
    from student in students
    group student by student.Last;

可是,使用 var 至少有可能使代碼對其餘開發人員更加難以理解。 爲此,C# 文檔一般只在須要時才使用 var

其餘技術請參閱

 

相關文章
相關標籤/搜索