暗黙的に型指定されるローカル変数 (C# プログラミング ガイド)Implicitly typed local variables (C# Programming Guide)

ローカル変数は、明示的な型を指定しないで宣言できます。Local variables can be declared without giving an explicit type. var キーワードは、初期化ステートメントの右辺にある式から変数の型を推論するようにコンパイラに指示します。The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement. 推論される型は、組み込み型、匿名型、ユーザー定義型、または .NET Framework クラス ライブラリで定義されている型である可能性があります。The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library. var で配列を初期化する方法の詳細については、「暗黙的に型指定される配列」を参照してください。For more information about how to initialize arrays with var, see Implicitly Typed Arrays.

ローカル変数を var で宣言するさまざまな方法を次の例に示します。The following examples show various ways in which local variables can be declared with 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 キーワードは "バリアント" を意味するのではなく、変数の厳密でない型指定や遅延バインディングを示すものでもないことを理解することが重要です。It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. 単に、最も適切な型をコンパイラが決定して割り当てることを意味します。It just means that the compiler determines and assigns the most appropriate type.

var キーワードは、次のコンテキストで使用される場合があります。The var keyword may be used in the following contexts:

  • 前の例で示したようなローカル変数 (メソッドのスコープで宣言された変数)。On local variables (variables declared at method scope) as shown in the previous example.

  • for 初期化ステートメント。In a for initialization statement.

    for (var x = 1; x < 10; x++)
    
  • foreach 初期化ステートメント。In a foreach initialization statement.

    foreach (var item in list) {...}
    
  • using ステートメント。In a using statement.

    using (var file = new StreamReader("C:\\myfile.txt")) {...}
    

詳細については、「「クエリ式で暗黙的に型指定されるローカル変数および配列を使用する方法」を参照してください。For more information, see How to use implicitly typed local variables and arrays in a query expression.

var と匿名型var and anonymous types

多くの場合、var の使用は任意であり、構文上便利なだけです。In many cases the use of var is optional and is just a syntactic convenience. ただし、変数が匿名型で初期化される場合、後でオブジェクトのプロパティへのアクセスが必要になったら、変数を var として宣言する必要があります。However, when a variable is initialized with an anonymous type you must declare the variable as var if you need to access the properties of the object at a later point. これは、LINQLINQ クエリ式では一般的なシナリオです。This is a common scenario in LINQLINQ query expressions. 詳細については、「匿名型」を参照してください。For more information, see Anonymous Types.

ソース コードの観点から見ると、匿名型には名前がありません。From the perspective of your source code, an anonymous type has no name. そのため、クエリ変数が var で初期化された場合、返されたオブジェクトのシーケンスのプロパティにアクセスするための唯一の方法は、foreach ステートメント内の繰り返し変数の型として var を使用することです。Therefore, if a query variable has been initialized with var, then the only way to access the properties in the returned sequence of objects is to use var as the type of the iteration variable in the foreach statement.

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

暗黙的に型指定される変数の宣言には、次の制限が適用されます。The following restrictions apply to implicitly-typed variable declarations:

  • var を使用できるのは、同じステートメント内でローカル変数の宣言と初期化が行われる場合のみです。この変数は、null、メソッド グループ、または匿名関数に初期化することはできません。var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.

  • var は、クラス スコープのフィールドで使用できません。var cannot be used on fields at class scope.

  • var を使用して宣言された変数は、初期化式では使用できません。Variables declared by using var cannot be used in the initialization expression. つまり、int i = (i = 20); という式は有効ですが、var i = (i = 20); という式はコンパイル時エラーが生成されます。In other words, this expression is legal: int i = (i = 20); but this expression produces a compile-time error: var i = (i = 20);

  • 暗黙的に型指定された複数の変数を同じステートメント内で初期化することはできません。Multiple implicitly-typed variables cannot be initialized in the same statement.

  • var という名前の型がスコープ内にある場合、var キーワードはその型名に解決され、暗黙的に型指定されたローカル変数の宣言の一部とは見なされません。If a type named var is in scope, then the var keyword will resolve to that type name and will not be treated as part of an implicitly typed local variable declaration.

var キーワードによる暗黙の型指定は、ローカル メソッド スコープの変数にのみ適用できます。Implicit typing with the var keyword can only be applied to variables at local method scope. 暗黙の型指定はクラス フィールドには使用できません。C# コンパイラでコードを処理するときに論理的パラドックスにぶつかるためです。コンパイラはフィールドの型を認識する必要がありますが、代入式が分析されるまで型を判断できません。そして、型を認識していなければ、式を評価できません。Implicit typing is not available for class fields as the C# compiler would encounter a logical paradox as it processed the code: the compiler needs to know the type of the field, but it cannot determine the type until the assignment expression is analyzed, and the expression cannot be evaluated without knowing the type. 次のコードがあるとします。Consider the following code:

private var bookTitles;

bookTitles は、型が var のクラス フィールドです。bookTitles is a class field given the type var. このフィールドには評価する式がないため、コンパイラでは bookTitles の型を推定できません。As the field has no expression to evaluate, it is impossible for the compiler to infer what type bookTitles is supposed to be. さらに、(ローカル変数の場合と同様に) フィールドに式を追加するだけでは不十分です。In addition, adding an expression to the field (like you would for a local variable) is also insufficient:

private var bookTitles = new List<string>();

コードのコンパイル中にコンパイラでフィールドが検出されると、それに関連付けられている式を処理する前に各フィールドの型が記録されます。When the compiler encounters fields during code compilation, it records each field's type before processing any expressions associated with it. コンパイラでの bookTitles の解析時に同じパラドックスにぶつかります。フィールドの型を認識する必要がありますが、通常、コンパイラは式を解析して var の型を判断します。これには、事前に型を認識している必要があります。The compiler encounters the same paradox trying to parse bookTitles: it needs to know the type of the field, but the compiler would normally determine var's type by analyzing the expression, which isn't possible without knowing the type beforehand.

var は、クエリ式と使用する場合に便利なこともあります。クエリ変数の構築された型を厳密に判別することが難しい場合です。You may find that var can also be useful with query expressions in which the exact constructed type of the query variable is difficult to determine. このような状況は、グループ化と並べ替えの処理で発生することがあります。This can occur with grouping and ordering operations.

var キーワードは、変数の特定の型をキーボードで入力するのが面倒な場合、その型が明白な場合、型によってコードが読みやすくならない場合にも役立ちます。The var keyword can also be useful when the specific type of the variable is tedious to type on the keyboard, or is obvious, or does not add to the readability of the code. このような理由で var が有用な例の 1 つとして、グループ化処理で使用されるような入れ子にされたジェネリック型があります。One example where var is helpful in this manner is with nested generic types such as those used with group operations. 次のクエリでは、クエリ変数の型は IEnumerable<IGrouping<string, Student>> です。In the following query, the type of the query variable is IEnumerable<IGrouping<string, Student>>. コードの作成者とそのコードを保守する担当者がこの点を理解している限り、簡略化するために暗黙的な型指定を使用しても問題はありません。As long as you and others who must maintain your code understand this, there is no problem with using implicit typing for convenience and brevity.

// 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 を使用すると、他の開発者がコードを理解しづらくなる可能性はあります。However, the use of var does have at least the potential to make your code more difficult to understand for other developers. このため、C# のドキュメントでは、通常、必要な場合にだけ var を使用しています。For that reason, the C# documentation generally uses var only when it is required.

関連項目See also