Неявно типизированные локальные переменные (руководство по программированию на 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 можно использовать только в том случае, если локальная переменная объявляется и инициализируется в одном и том же операторе; переменная не может инициализироваться в нулевое значение, в группу методов или в анонимную функцию.

  • 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#.

См. также