Например, если вы хотите получить значение для int в предыдущем примере, но остальные два параметра вас не волнуют, тогда можете написать такой код:
// Здесь будет получено значение только для а;
// значения для других двух параметров игнорируются.
FillTheseValues(out int a, out _, out _);
Обратите внимание, что вызываемый метод по-прежнему выполняет работу, связанную с установкой значений для всех трех параметров; просто последние два параметра отбрасываются, когда происходит возврат из вызова метода.
Модификатор out в конструкторах и инициализаторах (нововведение в версии 7.3)
В версии C# 7.3 были расширены допустимые местоположения для использования параметра out. В дополнение к методам параметры конструкторов, инициализаторы полей и свойств, а также конструкции запросов можно декорировать модификатором out. Примеры будут представлены позже в главе.
Использование модификатора ref
А теперь посмотрим, как в C# используется модификатор ref. Ссылочные параметры необходимы, когда вы хотите разрешить методу манипулировать различными элементами данных (и обычно изменять их значения), которые объявлены в вызывающем коде, таком как процедура сортировки или обмена.
Обратите внимание на отличия между ссылочными и выходными параметрами.
• Выходные параметры не нуждаются в инициализации перед передачей методу. Причина в том, что метод до своего завершения обязан самостоятельно присваивать значения выходным параметрам.
• Ссылочные параметры должны быть инициализированы перед передачей методу. Причина связана с передачей ссылок на существующие переменные. Если начальные значения им не присвоены, то это будет равнозначно работе с неинициализированными локальными переменными.
Давайте рассмотрим применение ключевого слова ref на примере метода, меняющего местами значения двух переменных типа string (естественно, здесь мог бы использоваться любой тип данных, включая int, bool, float и т.д.):
// Ссылочные параметры.
public static void SwapStrings(ref string s1, ref string s2)
{
string tempStr = s1;
s1 = s2;
s2 = tempStr;
}
Метод SwapStrings() можно вызвать следующим образом:
Console.WriteLine("***** Fun with Methods *****");
string str1 = "Flip";
string str2 = "Flop";
Console.WriteLine("Before: {0}, {1} ", str1, str2); // До
SwapStrings(ref str1, ref str2);
Console.WriteLine("After: {0}, {1} ", str1, str2); // После
Console.ReadLine();
Здесь вызывающий код присваивает начальные значения локальным строковым данным (str1 и str2). После вызова метода SwapStrings() строка str1 будет содержать значение "Flop", а строка str2 — значение "Flip":
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})
Before: Flip, Flop
After: Flop, Flip
Использование модификатора in (нововведение в версии 7.2)
Модификатор in обеспечивает передачу значения по ссылке (для типов значений и ссылочных типов) и препятствует модификации значений в вызываемом методе. Это четко формулирует проектный замысел в коде, а также потенциально снижает нагрузку на память. Когда параметры типов значений передаются по значению, они (внутренне) копируются вызываемым методом. Если объект является большим (вроде крупной структуры), тогда добавочные накладные расходы на создание копии для локального использования могут оказаться значительными. Кроме того, даже когда параметры ссылочных типов передаются без модификатора, в вызываемом методе их можно модифицировать. Обе проблемы решаются с применением модификатора in.
В рассмотренном ранее методе Add() есть две строки кода, которые изменяют параметры, но не влияют на значения для вызывающего метода. Влияние на значения отсутствует из-за того, что метод Add() создает копию переменных х и у с целью локального использования. Пока вызывающий метод не имеет неблагоприятных побочных эффектов, но что произойдет, если бы код метода Add() был таким, как показано ниже?
static int Add2(int x,int y)
{
x = 10000;
y = 88888;
int ans = x + y;
return ans;
}
В данном случае метод возвращает значение 98888 независимо от переданных ему чисел, что очевидно представляет собой проблему. Чтобы устранить ее, код метода понадобится изменить следующим образом:
static int AddReadOnly(in int x,in int y)
{
// Ошибка CS8331 Cannot assign to variable 'in int'
// because it is a readonly variable
// He удается присвоить значение переменной in int,
// поскольку она допускает только чтение
// х = 10000;
// у = 88888;
int ans = x + y;
return ans;
}
Когда в коде предпринимается попытка изменить значения параметров, компилятор сообщит об ошибке CS8331, указывая на то, что значения не могут быть изменены из-за наличия модификатора in.