Var си шарп это

Declaration statements

A declaration statement declares a new local variable, local constant, or local reference variable. To declare a local variable, specify its type and provide its name. You can declare multiple variables of the same type in one statement, as the following example shows:

string greeting; int a, b, c; List xs; 

In a declaration statement, you can also initialize a variable with its initial value:

string greeting = "Hello"; int a = 3, b = 2, c = a + b; List xs = new(); 

The preceding examples explicitly specify the type of a variable. You can also let the compiler infer the type of a variable from its initialization expression. To do that, use the var keyword instead of a type’s name. For more information, see the Implicitly-typed local variables section.

To declare a local constant, use the const keyword, as the following example shows:

const string Greeting = "Hello"; const double MinLimit = -10.0, MaxLimit = -MinLimit; 

When you declare a local constant, you must also initialize it.

For information about local reference variables, see the Reference variables section.

Implicitly-typed local variables

When you declare a local variable, you can let the compiler infer the type of the variable from the initialization expression. To do that use the var keyword instead of the name of a type:

var greeting = "Hello"; Console.WriteLine(greeting.GetType()); // output: System.String var a = 32; Console.WriteLine(a.GetType()); // output: System.Int32 var xs = new List(); Console.WriteLine(xs.GetType()); // output: System.Collections.Generic.List`1[System.Double] 

As the preceding example shows, implicitly-typed local variables are strongly typed.

Читайте также:  Глобальные стили

When you use var in the enabled nullable aware context and the type of an initialization expression is a reference type, the compiler always infers a nullable reference type even if the type of an initialization expression isn’t nullable.

A common use of var is with a constructor invocation expression. The use of var allows you to not repeat a type name in a variable declaration and object instantiation, as the following example shows:

Beginning with C# 9.0, you can use a target-typed new expression as an alternative:

List xs = new(); List? ys = new(); 

When you work with anonymous types, you must use implicitly-typed local variables. The following example shows a query expression that uses an anonymous type to hold a customer’s name and phone number:

var fromPhoenix = from cust in customers where cust.City == "Phoenix" select new < cust.Name, cust.Phone >; foreach (var customer in fromPhoenix) < Console.WriteLine($"Name=, Phone="); > 

For more information about implicitly-typed local variables, see Implicitly-typed local variables.

In pattern matching, the var keyword is used in a var pattern.

Reference variables

When you declare a local variable and add the ref keyword before the variable’s type, you declare a reference variable, or a ref local:

ref int alias = ref variable; 

A reference variable is a variable that refers to another variable, which is called the referent. That is, a reference variable is an alias to its referent. When you assign a value to a reference variable, that value is assigned to the referent. When you read the value of a reference variable, the referent’s value is returned. The following example demonstrates that behavior:

int a = 1; ref int alias = ref a; Console.WriteLine($"(a, alias) is (, )"); // output: (a, alias) is (1, 1) a = 2; Console.WriteLine($"(a, alias) is (, )"); // output: (a, alias) is (2, 2) alias = 3; Console.WriteLine($"(a, alias) is (, )"); // output: (a, alias) is (3, 3) 

Use the ref assignment operator = ref to change the referent of a reference variable, as the following example shows:

void Display(int[] s) => Console.WriteLine(string.Join(" ", s)); int[] xs = < 0, 0, 0 >; Display(xs); ref int element = ref xs[0]; element = 1; Display(xs); element = ref xs[^1]; element = 3; Display(xs); // Output: // 0 0 0 // 1 0 0 // 1 0 3 

In the preceding example, the element reference variable is initialized as an alias to the first array element. Then it’s ref reassigned to refer to the last array element.

You can define a ref readonly local variable. You can’t assign a value to a ref readonly variable. However you can ref reassign such a reference variable, as the following example shows:

int[] xs = < 1, 2, 3 >; ref readonly int element = ref xs[0]; // element = 100; error CS0131: The left-hand side of an assignment must be a variable, property or indexer Console.WriteLine(element); // output: 1 element = ref xs[^1]; Console.WriteLine(element); // output: 3 

You can assign a reference return to a reference variable, as the following example shows:

using System; public class NumberStore < private readonly int[] numbers = < 1, 30, 7, 1557, 381, 63, 1027, 2550, 511, 1023 >; public ref int GetReferenceToMax() < ref int max = ref numbers[0]; for (int i = 1; i < numbers.Length; i++) < if (numbers[i] >max) < max = ref numbers[i]; >> return ref max; > public override string ToString() => string.Join(" ", numbers); > public static class ReferenceReturnExample < public static void Run() < var store = new NumberStore(); Console.WriteLine($"Original sequence: "); ref int max = ref store.GetReferenceToMax(); max = 0; Console.WriteLine($"Updated sequence: "); // Output: // Original sequence: 1 30 7 1557 381 63 1027 2550 511 1023 // Updated sequence: 1 30 7 1557 381 63 1027 0 511 1023 > > 

In the preceding example, the GetReferenceToMax method is a returns-by-ref method. It doesn’t return the maximum value itself, but a reference return that is an alias to the array element that holds the maximum value. The Run method assigns a reference return to the max reference variable. Then, by assigning to max , it updates the internal storage of the store instance. You can also define a ref readonly method. The callers of a ref readonly method can’t assign a value to its reference return.

The iteration variable of the foreach statement can be a reference variable. For more information, see the foreach statement section of the Iteration statements article.

In performance-critical scenarios, the use of reference variables and returns might increase performance by avoiding potentially expensive copy operations.

The compiler ensures that a reference variable doesn’t outlive its referent and stays valid for the whole of its lifetime. For more information, see the Ref safe contexts section of the C# language specification.

For information about the ref fields, see the ref fields section of the ref structure types article.

scoped ref

The contextual keyword scoped restricts the lifetime of a value. The scoped modifier restricts the ref-safe-to-escape or safe-to-escape lifetime, respectively, to the current method. Effectively, adding the scoped modifier asserts that your code won’t extend the lifetime of the variable.

You can apply scoped to a parameter or local variable. The scoped modifier may be applied to parameters and locals when the type is a ref struct . Otherwise, the scoped modifier may be applied only to local reference variables. That includes local variables declared with the ref modifier and parameters declared with the in , ref or out modifiers.

The scoped modifier is implicitly added to this in methods declared in a struct , out parameters, and ref parameters when the type is a ref struct .

C# language specification

For more information, see the following sections of the C# language specification:

For more information about the scoped modifier, see the Low-level struct improvements proposal note.

See also

Источник

Неявно типизированные локальные переменные (руководство по программированию на 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 // or perhaps IQueryable 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 var list = new List(); 

Важно понимать, что ключевое слово var не означает «variant» и не означает, что переменная является слабо типизированной или имеет позднее связывание. Он указывает только на то, что компилятор определяет и назначает наиболее подходящий тип.

Ключевое слово var можно использовать в следующих контекстах:

  • С локальными переменными (переменными, объявленными в области метода), как показано в предыдущем примере.
  • В операторе инициализации for.
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: , Lowercase: ", 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#, так как при обработке кода компилятор столкнется с логическим парадоксом: компилятор должен знать тип поля, но он не может определить тип, пока не проанализирует выражение присваивания, и не может вычислить выражение, не зная тип. Рассмотрим следующий код.

bookTitles — это поле класса, которому присваивается тип var . Так как поле не имеет выражения для оценки, то компилятор не сможет вывести тип bookTitles . Кроме того, добавления выражения в поле (так же, как для локальной переменной) тоже недостаточно:

private var bookTitles = new List(); 

Когда компилятор обнаруживает поля во время компиляции кода, он записывает тип каждого поля перед обработкой любого выражения, связанного с ним. Компилятор обнаруживает тот же парадокс при попытке анализа bookTitles : он должен знать тип поля, но обычно он определяет тип var путем анализа выражения, который невозможно определить, если заранее не знать тип.

Переменную var можно также использовать в выражениях запросов, где точный сконструированный тип переменной запроса определить непросто. Подобная ситуация может возникнуть в операциях группировки и сортировки.

Кроме того, ключевое слово var может пригодиться, если конкретный тип переменной сложно набрать с клавиатуры, а также если он очевиден либо затрудняет чтение кода. Использовать var таким образом можно, например, с вложенными универсальными типами — подобные типы применяются в групповых операциях. В следующем запросе переменная запроса имеет тип IEnumerable> . Если вы и другие пользователи, которые работают с кодом, это понимаете, использовать неявный ввод для удобства и краткости кода можно без проблем.

// Same as previous example except we use the entire last name as a key. // Query variable is an IEnumerable> var studentQuery3 = from student in students group student by student.Last; 

Ключевое слово var позволяет упростить код, однако его следует использовать только там, где оно действительно необходимо или где оно облегчает понимание кода. Дополнительные сведения о том, когда следует использовать ключевое слово var , см. в разделе Неявно типизированные локальные переменные в статье с рекомендациями по написанию кода C#.

См. также

Источник

Оцените статью