Си шарп значения переменных

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

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

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 в контексте, допускающего значение NULL , и тип выражения инициализации является ссылочным типом, компилятор всегда выводит ссылочный тип, допускающий значение NULL , даже если тип выражения инициализации не допускает значения NULL.

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

Начиная с C# 9.0, в качестве альтернативы можно использовать выражение целевого типа 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 alias = ref variable; 

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

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) 

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 метод является методом returns-by-ref . Он возвращает не максимальное значение, а возвращает ссылку, которая является псевдонимом элемента массива, который содержит максимальное значение. Метод Run назначает возвращаемую ссылку ссылочной переменной max . Затем, назначив параметру max , он обновляет внутреннее хранилище экземпляра store . Вы также можете определить ref readonly метод . ref readonly Вызывающие методы не могут присвоить значение возвращаемой ссылке.

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

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

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

Сведения о полях см. в ref ref разделе поля статьи о типах 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 см. в примечании к предложению по улучшению низкоуровневой структуры .

См. также раздел

Источник

Типы значений (справочник по C#)

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

using System; public struct MutablePoint < public int X; public int Y; public MutablePoint(int x, int y) =>(X, Y) = (x, y); public override string ToString() => $"(, )"; > public class Program < public static void Main() < var p1 = new MutablePoint(1, 2); var p2 = p1; p2.Y = 200; Console.WriteLine($"after is modified: "); Console.WriteLine($": "); MutateAndDisplay(p2); Console.WriteLine($" after passing to a method: "); > private static void MutateAndDisplay(MutablePoint p) < p.X = 100; Console.WriteLine($"Point mutated in a method: 

"); > > // Expected output: // p1 after p2 is modified: (1, 2) // p2: (1, 200) // Point mutated in a method: (100, 200) // p2 after passing to a method: (1, 200)

Как показано в предыдущем примере, операции с переменной типа значения влияют только на этот экземпляр типа значения, хранящийся в переменной.

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

using System; using System.Collections.Generic; public struct TaggedInteger < public int Number; private Listtags; public TaggedInteger(int n) < Number = n; tags = new List(); > public void AddTag(string tag) => tags.Add(tag); public override string ToString() => $" []"; > public class Program < public static void Main() < var n1 = new TaggedInteger(0); n1.AddTag("A"); Console.WriteLine(n1); // output: 0 [A] var n2 = n1; n2.Number = 7; n2.AddTag("B"); Console.WriteLine(n1); // output: 0 [A, B] Console.WriteLine(n2); // output: 7 [A, B] >> 

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

Виды типов значений и ограничения типов

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

  • тип структуры, который инкапсулирует данные и связанные функции;
  • тип перечисления, который определяется набором именованных констант и представляет выбор или сочетание вариантов для выбора.

Тип T? значения, допускающий значение NULL, представляет все значения базового типа T значения и дополнительное значение NULL. Вы не можете назначить null переменной типа значения, если только это не тип, допускающий значение NULL.

Вы можете использовать ограничение struct , чтобы указать, что параметр типа является типом значения, не допускающим значения NULL. Типы структуры и перечисления удовлетворяют ограничению struct . Можно использовать System.Enum в ограничении базового класса (которое называется ограничением перечисления), чтобы указать, что параметр типа является типом перечисления.

Встроенные типы значений

C# предоставляет следующие встроенные типы значений, которые также называются простыми типами.

  • Целочисленные типы
  • Числовые типы с плавающей запятой
  • bool, представляющий логическое значение
  • char, представляющий символ Юникода UTF-16

Все простые типы являются типами структур и отличаются от других типов структур тем, что разрешают некоторые дополнительные операции.

  • Литералы можно использовать для предоставления значения простого типа. Например, ‘A’ — это литерал типа char , а 2001 — литерал типа int .
  • Константы простых типов можно объявить с помощью ключевого слова const. Невозможно использовать константы других типов структур.
  • Константные выражения, операнды которых являются константами простых типов, вычисляются во время компиляции.

Кортеж значений — это тип значения, но не простой тип.

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

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

См. также раздел

Источник

Читайте также:  Operator priority in javascript
Оцените статью