Var c что это
Перейти к содержимому

Var c что это

  • автор:

Var c что это

Ключевое слово var ссылается на тип неявным способом. Это псевдоним любого типа. Реальный тип определит компилятор C#. Использование var никак не ухудшает производительность. Var это отличный (и вкусный) синтаксический «сахар». Он делает программы короче и проще для чтения. Var может использоваться в коде методов и в теле циклов. Ключевое слово var может представлять любой тип, и какой это будет тип определяется во время компиляции. После компиляции результат получится тот же самый, как если бы тип был точно указан.

Рассмотрим примеры применения ключевого слова var. Ниже показано использование var в трех контекстах.

Примечание: для компиляции этой программы Вы не можете использовать старую версию .NET Framework (используйте .NET 2017).

using System;
using System.Collections.Generic;
using System.Linq;
class Program < public static void Main() < // 1. // var доступно всегда, не только в Linq. var cat = new List< int> < 1, 2, 7, 9 >; // Наведите курсор на ключевое слово 'var', и Visual Studio // скажет Вам какой реально тип здесь используется. 
// 2. // Этот пример отображает нечетные числа. // Возвращает IEnumerable < T>(где T это int). var items = from item in cat where (item % 2 == 1) select item;
// 3. // Каждый элемент имеет тип int. foreach (var item in items) < Console.WriteLine(item); >// Предыдущий цикл такой же, как и предыдущий: foreach (int item in items) < Console.WriteLine(item); >> >
1 7 9
1 7 9

Этот код использует ключевое слово var и тип List. Переменная известна как List. Таким образом, var относится к List элементов типа int.

Примечание: Вы можете навести курсор мыши на var, и среда Visual Studio подскажет, что это тип List. Эта функция называется IntelliSense.

В этом примере также показан запрос к элементам var, который возвращает IEnumerable< int>. Выражение запроса вычисляется для этого типа, и var неявно относится к этому типу.

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

Системы обработки типов. Язык C# использует строгий контроль типов. Области памяти помечены информацией о том, какие типы объектов в них содержатся. Строгий контроль типов помогает повысить качество кода. Компилятор C# будет выдавать ошибки и предупреждения, потому что хочет, чтобы Ваш код работал правильно. В случае var он анализирует код, и выводит из него тип переменной.

Ограничения. Вы не можете назначить var в значение null. Это приведет к предупреждению CS0825. Также Вы не можете использовать var в качестве типа параметра или возвращаемого значения метода.

Реализация. Давайте посмотрим на поведение реализации кода C#, который использует ключевое слово var. Реальное поведение кода C# отражает промежуточный язык (IL, Intermediate Language). Код IL можно посмотреть с помощью утилиты IL Disassembler, предоставляемой Visual Studio. В примере используются два значения типа int32, и эти два значения на IL абсолютно одинаковые, хотя одна декларация использует var, а другая int. Подсистема выполнения кода ничего не знает о том, что программист использовал var. Таким образом переменная, определенная с ключевым словом var, будет работать точно так же эффективно, как и переменная, определенная с явным указанием типа наподобие int или string.

public int ReturnValue() < var a = 5; int b = 5;
return a + b; >

Код IL этого метода:

.method public hidebysig instance int32 ReturnValue() cil managed < // Code size 9 (0x9) .maxstack 1 .locals init ([0] int32 result,
 [1] int32 CS$1$0000) IL_0000: nop IL_0001: ldc.i4.5 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: stloc.1 IL_0005: br.s IL_0007 IL_0007: ldloc.1 IL_0008: ret > // end of method VarKW::ReturnValue 

Использование. Ключевое слово var полезно не только на обычных типах. Ниже показан тип Dictionary, использующий подробный синтаксис — много скобок, букв и запятых. Var позволяет опустить длинные списки типов параметров, что может улучшить читаемость кода. Var часто упрощает ревизию/переработку (refactoring) кода.

Примечание: когда при рефакторинге Вы меняете имя типа, то локальный тип var не нуждается в замене.

// Программа C#, использующая var для типа Dictionary.
using System;
using System.Collections.Generic;
class Program < static void Main() < // Использование ключевого слова var для создания экземпляра Dictionary. // Затем используем саму коллекцию. var data = new Dictionary< string, int>(); data.Add("cat", 2); data.Add("dog", 1); Console.WriteLine("cat - dog = ", data["cat"] - data["dog"]); > >
cat - dog = 1

Общие выводы. Var полезное ключевое слово. Оно похоже на #define или typedef языка C++. Мы используем var для краткости, это делает код проще для понимания. В некоторых случаях var может запутать, тогда используйте здравый смысл для организации кода.

[Ссылки]

1. var keyword site:dotnetperls.com.
2. var (справочник по C#) site:docs.microsoft.com.

Инструкции объявления

Оператор объявления объявляет новую локальную переменную, локальную константу или локальную эталонную переменную. Чтобы объявить локальную переменную, укажите его тип и укажите его имя. Можно объявить несколько переменных одного типа в одной инструкции, как показано в следующем примере:

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

В инструкции объявления можно также инициализировать переменную с его начальным значением:

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

В предыдущих примерах явно указывается тип переменной. Можно также разрешить компилятору определить тип переменной из его выражения инициализации. Для этого используйте var ключевое слово вместо имени типа. Дополнительные сведения см. в разделе неявно типизированных локальных переменных .

Чтобы объявить локальную константу, используйте const ключевое слово, как показано в следующем примере:

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

При объявлении локальной константы необходимо также инициализировать ее.

Сведения о локальных ссылочных переменных см. в разделе «Эталонные переменные «.

Неявно типизированные локальные переменные

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

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] 

Как показано в предыдущем примере, неявно типизированные локальные переменные строго типизированы.

Обычно используется выражение var вызова конструктора. Использование var позволяет вам не повторять имя типа при объявлении переменной и создании экземпляра объекта, как показано в следующем примере:

var xs = new List(); 

Вы можете использовать целевое типизированное new выражение в качестве альтернативы:

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

При работе с анонимными типами необходимо использовать неявно типизированные локальные переменные. В следующем примере показано выражение запроса, которое использует анонимный тип для хранения имени клиента и номера телефона:

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="); > 

Дополнительные сведения о неявно типизированных локальных переменных см. в разделе неявно типизированные локальные переменные.

При сопоставлении шаблонов в шаблоне var используется ключевое слово var .

Ссылочные переменные

При объявлении локальной переменной и добавлении ref ключевое слово перед типом переменной объявляется эталонная переменная или локальная ref :

ref int aliasOfvariable = ref variable; 

Ссылочная переменная — это переменная, которая ссылается на другую переменную, которая называется ссылочной. То есть ссылочная переменная является псевдонимом его ссылки. При назначении значения ссылочной переменной это значение назначается референту. При чтении значения ссылочной переменной возвращается значение ссылки. В следующем примере продемонстрировано такое поведение.

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

ref Используйте оператор = ref назначения для изменения ссылочной переменной, как показано в следующем примере:

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 

В предыдущем примере element ссылочная переменная инициализируется как псевдоним первого элемента массива. Затем он ref переназначился, чтобы ссылаться на последний элемент массива.

Можно определить локальную ref readonly переменную. Нельзя назначить значение переменной ref readonly . Однако можно ref переназначить такую эталонную переменную, как показано в следующем примере:

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 

Вы можете назначить ссылку в эталонную переменную, как показано в следующем примере:

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

В предыдущем примере GetReferenceToMax метод является методом возвращается по ссылке . Он не возвращает максимальное значение, но возвращаемое ссылкой, которое является псевдонимом элемента массива, который содержит максимальное значение. Метод Run назначает ссылку возвращаемой переменной max . Затем, назначив max его, он обновляет внутреннее хранилище экземпляра store . Можно также определить ref readonly метод. Вызывающие методы ref readonly не могут назначить значение возвращаемой ссылке.

Переменная итерации инструкции foreach может быть эталонной переменной. Дополнительные сведения см. в foreach разделе инструкций инструкции инструкций итерации.

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

Сведения о ref полях см ref . в разделе полей статьи ref типов структур.

область d ref

Контекстная ключевое слово scoped ограничивает время существования значения. Модификатор scoped ограничивает время существования ref-safe-to-escape или safe-to-escape соответственно текущим методом. Фактически добавление модификатора утверждает, scoped что код не будет расширять время существования переменной.

Можно применить scoped к параметру или локальной переменной. Модификатор scoped может применяться к параметрам и локальным параметрам, если тип является типом ref struct . scoped В противном случае модификатор может применяться только к локальным ссылочным переменным. Это включает локальные переменные, объявленные модификатором ref и параметрами, объявленными с in ref помощью модификаторов или out модификаторов.

Модификатор scoped неявно this добавляется в методы, объявленные в struct параметрах out , параметрах и ref параметрах, когда тип является ref struct .

Спецификация языка C#

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:

  • Инструкции объявления
  • Ссылочные переменные и возвращается

Дополнительные сведения об scoped модификаторе см. в заметке по улучшению структуры низкого уровня.

См. также

  • Инициализаторы объектов и коллекций
  • Ключевое слово ref
  • Сокращение выделения памяти с помощью новых функций C#
  • Параметры var (правила стиля IDE0007 и IDE0008)

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

.NET, C# и все-все-все

Контекстное ключевое слово ‘var’ было впервые представленное в C# 3.0. Оно описано, как «контекстное» т.к. является ключевым в определенном контексте. В остальных случаях — это обычный идентификатор.

Контекстные ключевые слова не являются чем-то новым. Еще в C# 1.0 были представлены такие контекстные ключевые слова, как get, set, value, add и remove — которые используются в контексте определения свойств и событий. Другие контекстные ключевые слова были добавлены в последующих версиях.

‘var’ является инструкцией для компилятора C#, позволяющей определить тип локальной переменной из типа присваиваемого ей значения. Например:

var list = new List(); // list принадлежит типу List var count = 3; // count принадлежит типу int var greeting = "Hello"; // greeting принадлежит типу string var var = 'c'; // var (в роли имени переменной) принадлежит типу 'char' 

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

greeting = 5; // недопустимо т.к. greeting имеет тип string 

‘var’ является строго типизированным, хотя может показаться, что это не так.

Так в чем же заключается проблема?
‘var’ является одним из самых спорных дополнений в C#.

Одни C# разработчики любят его и используют где только это возможно; другие же разработчики, напротив, ненавидят ‘var’ и используют его тогда, когда другого варианта просто нет. Остальные же находятся где-то между этими двумя крайностями, хотя многие и не имеют продуманной или четкой политики по этому поводу.

Те, кто любит ‘var’, говорят, что его использование уменьшает количество ввода, количество строк и убирает необходимость в дублировании типа переменной с двух сторон оператора присваивания во время инициализации объекта (многие разработчики сетовали по этому поводу на версии 1.0 и 2.0). В любом случае, если закрались, какие-либо сомнения в отношении типа переменной, то Intellisense поможет их развеять.

Те, кто ненавидит ‘var’, говорят, что код становится нечитабельным (а обычно код читают чаще, нежели пишут) и подстрекают к использованию «уродливой» венгерской нотации чтобы тип переменной был ясен из ее имени. К примеру, iCount — переменная типа int или sGreeting — тип string. Да и во время «чтения» кода Intellisense не всегда может быть под рукой.

Даже выбор ключевого слова для не типизированной переменной сомнителен. Многие разработчики считают, что ‘var’ является плохим выбором из-за намека на слабо типизированное ключевое слово ‘var’ в Java Script или на варианты в языках, основанных на COM (таких как VB6), которые могут принимать значения любых типов.

Последняя версия Visual C++ использует ключевое слово ‘auto’ для выполнения аналогичной роли. Вероятно, подобный выбор для C# был бы лучше, хотя наверняка впоследствии начали бы поступать жалобы от программистов, работающих в автомобильной индустрии!

Когда вы должны использовать ‘var’?

‘var’ необходимо использовать при объявлении переменных анонимного типа или коллекций анонимных типов. По определению эти типы не имеют имен (у них нет имен, по которым к ним можно было бы нормально обращаться из C#). Поэтому нужно писать:

var anonymous = newFirstName = "John", LastName = "Doe">; var query = from name in names where name.StartsWith("A") select new  Initial = name[0], LastName = name.Split(' ')[1]>; 

Когда ‘var’ использовать нельзя?

Использование ‘var’ запрещено для объявления локальных переменных внутри методов или свойств, включая итерационные переменные в ‘for’ и ‘foreach’ выражениях. Это значит, что ‘var’ запрещено использовать в любом из следующих сценариев:
— в качестве типа поля
— в качестве типа параметра
— в качестве типа возвращаемого методом или свойством
— в качестве типа параметра в обобщенном типе или методе
Его также запрещено использовать, если уже есть одноименный тип в той же области видимости:

class var  static void Main()  var v = "Hello"; // нельзя неявно привести к типу из 'string' в 'var' > > 

Не может быть использован в выражениях, где тип ‘var’ нельзя определить:

var n = null; // Нельзя присвоить 'null' неявно типизированной локальной переменной 

Когда следует использовать ‘var’?
Так существует ли золотая середина, с которой могли бы согласиться те из нас, кто не определился со своим отношением к ‘var’?

Главное возражение в отношении беспорядочного использования ‘var’ состоит в том, что код становится нечитабельным т.к. сложно, взглянув на код, сразу сказать к какому типу принадлежит переменная — придется сначала хорошенько задуматься, но даже после этого не всегда удастся правильно ответить на данный вопрос.

Это говорит о том, что было бы разумно ограничить использование ‘var’ случаями, когда тип очевиден т.к. он явно используется с правой стороны оператора присваивания. Это следующие случаи:
— оператор ‘new’
— ‘static’ методы, возвращающие значение такого же типа
— выражения с простым приведением типов

— выражения, включающие преобразование с помощью оператора ‘as’

Несколько примеров для наглядности:

var ht = new Hashtable(); //оператор 'new' var dt = DateTime.Parse("1/1/2011"); //статический метод ht.Add(1,dt); var dt2 = (DateTime)ht[1]; //простое приведение типов var dict = ht as IDictionary; //преобразование с помощью оператора 'as' 

Конечно, во всех этих случаях вы можете возразить, что не обязательно присвоили бы эти значения переменными “очевидного” типа. А присвоили бы их скорее переменной типа, к которой “очевидный” тип неявно преобразуется (скажем “object” в вышеупомянутых случаях). Однако, в таком случае, ничего не мешало бы явно определить тип переменной т.к. уже имеется смешение явных и неявных присваиваний (в случае если вы следовали этим условиям).

Даже если вы согласитесь, что эти ограничения рациональны, все равно придется решать насколько длинным должно быть имя типа для экономии времени ввода, длины строки и дублирования типа переменной, чтобы все это имело смысл. Я думаю, вы наверняка могли бы сказать, что все это имеет смысл для любых обобщенных типов, но как насчет необобщенных типов?

Хотя это крайне субъективно, но с моей точки зрения все это не имеет смысла, пока имя необобщенного типа состоит, по меньшей мере, из восьми символов, что удобно исключает из рассмотрения встроенные типы (string, double, decimal и т.д.).

Не все ли равно, что вы делаете?
Я считаю, что не все равно.

Когда вы пишите код, вас не должен мучить вопрос, “а стоит ли здесь использовать ‘var’ или нет?” Вам нужно четкое понимание того, когда (если вообще необходимо) следует им пользоваться, дабы решение принималось моментально.

Аналогично, когда вы просматриваете код, тратить несколько секунд пытаясь решить, к какому типу принадлежит переменная не очень то и хочется – хочется определить это моментально.

Даже если вы не согласны с моим «здравым предложением о золотой середине», я надеюсь, что, по крайней мере, данная статья поможет вам решить вопрос с выбором стратегии в использовании ‘var’, подходящей именно вам!
Перевод статьи: When should you use the ‘var’ keyword in C#?

Что такое var в C#?

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

Особенности:

  1. Типопеременная: Переменные, объявленные с использованием var , являются типопеременными, что означает, что их тип определяется во время компиляции.
  2. Инференция типов: Процесс автоматического определения типа переменной называется «инференцией типов» и обеспечивает безопасность типов вместе с гибкостью языка.

Синтаксис:

// Использование var для объявления переменной var myVariable = "Привет, мир!"; // Пример использования var в цикле var numbers = new int[] < 1, 2, 3, 4, 5 >; foreach (var number in numbers)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *