Инструкции объявления
Оператор объявления объявляет новую локальную переменную, локальную константу или локальную эталонную переменную. Чтобы объявить локальную переменную, укажите его тип и укажите его имя. Можно объявить несколько переменных одного типа в одной инструкции, как показано в следующем примере:
string greeting;
int a, b, c;
List<double> xs;
В инструкции объявления можно также инициализировать переменную с его начальным значением:
string greeting = "Hello";
int a = 3, b = 2, c = a + b;
List<double> 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<double>();
Console.WriteLine(xs.GetType()); // output: System.Collections.Generic.List`1[System.Double]
Как показано в предыдущем примере, неявно типизированные локальные переменные строго типизированы.
Примечание.
При использовании var
в контексте с поддержкой, допускающего значение NULL, и тип выражения инициализации является ссылочным типом, компилятор всегда вводит ссылочный тип, допускающий значение NULL, даже если тип выражения инициализации не является пустым.
Обычно используется выражение var
вызова конструктора. Использование var
позволяет вам не повторять имя типа при объявлении переменной и создании экземпляра объекта, как показано в следующем примере:
var xs = new List<int>();
Вы можете использовать целевое типизированное new
выражение в качестве альтернативы:
List<int> xs = new();
List<int>? 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={customer.Name}, Phone={customer.Phone}");
}
В предыдущем примере нельзя явно указать тип переменной fromPhoenix
. Тип, IEnumerable<T> но в этом случае T
является анонимным типом, и вы не можете указать его имя. Вот почему вам нужно использовать var
. По той же причине необходимо использовать var
при объявлении переменной customer
итерации в инструкции foreach
.
Дополнительные сведения о неявно типизированных локальных переменных см. в разделе неявно типизированные локальные переменные.
При сопоставлении шаблонов в шаблонеvar
используется ключевое слово var
.
Ссылочные переменные
При объявлении локальной переменной и добавлении ref
ключевого слова перед типом переменной объявляется эталонная переменная или локальная ref
:
ref int aliasOfvariable = ref variable;
Ссылочная переменная — это переменная, которая ссылается на другую переменную, которая называется ссылочной. То есть ссылочная переменная является псевдонимом его ссылки. При назначении значения ссылочной переменной это значение назначается референту. При чтении значения ссылочной переменной возвращается значение ссылки. В следующем примере продемонстрировано такое поведение.
int a = 1;
ref int aliasOfa = ref a;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})"); // output: (a, aliasOfa) is (1, 1)
a = 2;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})"); // output: (a, aliasOfa) is (2, 2)
aliasOfa = 3;
Console.WriteLine($"(a, aliasOfa) is ({a}, {aliasOfa})"); // 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: {store.ToString()}");
ref int max = ref store.GetReferenceToMax();
max = 0;
Console.WriteLine($"Updated sequence: {store.ToString()}");
// 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" спецификации языка C#.
Сведения о ref
полях см 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
модификаторе см. в заметке по улучшению структуры низкого уровня.