暗黙的に型指定されるローカル変数 (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 キーワードは "バリアント" を意味するのではなく、変数の厳密でない型指定や遅延バインディングを示すものでもないことを理解することが重要です。 単に、最も適切な型をコンパイラが決定して割り当てることを意味します。

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 で初期化された場合、返されたオブジェクトのシーケンスのプロパティにアクセスするための唯一の方法は、foreach ステートメント内の繰り返し変数の型として var を使用することです。

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
 */

Remarks

暗黙的に型指定される変数の宣言には、次の制限が適用されます。

  • 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 が有用な例の 1 つとして、グループ化処理で使用されるような入れ子にされたジェネリック型があります。 次のクエリでは、クエリ変数の型は 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# コーディング ガイドラインの記事の「暗黙的に型指定されるローカル変数」セクションを参照してください。

関連項目