Передача параметров по ссылке и значению (ключевые слова in, out и ref) - C# и .NET

Передача параметров по ссылке и значению (ключевые слова in, out и ref)

Передача параметров по ссылке и значению в C# – это два способа передачи параметров в методы. В этой части мы изучим эти способы и разберемся в чем их отличие, а также изучим вопрос о выходных параметрах методов.

Передача параметров по ссылке и значению

Передача параметров по значению

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

int i = 1;

Console.WriteLine(Add(i));
Console.WriteLine(i);

int Add(int a)
{
    a++;
    return a;
}

здесь метод Add()принимает в качестве параметра число, которое увеличивает на 1 и возвращает полученное значение. При этом, параметр передается по значению. Не запуская приложение, попробуйте ответить на вопрос: чему будет равно значение переменной i? Правильный ответ : переменная также и останется равной 1:Передача параметров по ссылке и значениюДело в том, что в метод мы передаем не саму переменную, а её копию. Значение копии увеличивается на 1 и возвращается нам методом, а сама переменная остается такой же какой и была.  Такой способ передачи параметров называется передачей по значениюГоворя проще, передача параметра по значению позволяет сохранить значение переменной, которое было до вызова метода. Иначе работает передача параметров по ссылке.

Передача параметров по ссылке

Ключевое слово ref

Ключевое слово refпозволяет передавать аргумент по ссылке. Если мы передаем параметр по ссылке, то значение параметра можно изменить внутри метода, например, перепишем наш  метод

int Add(ref int i)
{
    i++;
    return i;
}

Теперь параметр метода должен передаваться по ссылке и параметр в вызове метода должен также содержать ключевое слово ref, например,

Console.WriteLine(Add(ref i));

Проверим работу нашей программы при передаче параметра по ссылке:Передача параметров по ссылке и значению

Как можно видеть по рисунку, значение переменной, передаваемой в качестве параметра в метод, также изменилось.

Ключевое слово out

Ключевое слово out также используется для передачи параметров по ссылке. Оно похоже на ключевое слово ref , однако, при использовании ключевого слова outот нас не требуется инициализация переменной перед её передачей в качестве параметра метода. Например, попробуем переписать нашу программу следующим образом:

int i;//не инициализируем переменную перед передачей в метод

Console.WriteLine(Add(ref i));
Console.WriteLine(i);

Console.ReadKey();

int Add(ref int i)
{
    i++;
    return i;
}

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

Использование локальной переменной “i”, которой не присвоено значение.

С ключевым словом outмы можем не инициализировать переменную перед передачей её в качестве параметра в метод:

int i;//не инициализируем переменную перед передачей в метод

Console.WriteLine(Add(out i));
Console.WriteLine(i);

Console.ReadKey();

int Add(out int i)
{
    i = 0;//присвоили переменной начальное значение
    i++;
    return i;
}

Параметры метода, использующие ключевое слово outтакже иногда называют выходными параметрами метода. Переменные, передаваемые по ссылке, можно определять сразу в вызове метода, то есть вызов метода Add()в предыдущем примере можно переписать вот так:

Console.WriteLine(Add(out int i));
Console.WriteLine(i);

Console.ReadKey();

int Add(out int i)
{
    i = 0;//присвоили переменной начальное значение
    i++;
    return i;
}

Ключевое слово in

Кроме выходных параметров метода, объявляемых с модификатором out, в C# можно также определить входные параметры, передаваемые по ссылке с использованием ключевого слова in. Параметр с модификатором inпередается по ссылке, но внутри метода его изменять нельзя. Может возникнуть резонный вопрос: зачем нам тогда такой модификатор?

Когда используется передача параметра по значению, то внутри метода создается точная копия переменной, когда по ссылке — в метод передается только адрес в памяти где лежит значение. Когда мы имеем дело с переменными простых типов, типа 5299.9, то особых проблем нет — на современных компьютерах мы даже не заметим,  что программа «отъела» лишние байты памяти.  А теперь представим,  что в метод передается структура «весом» с сотню мегабайт. Передача по значению приведет к тому, что у нас в памяти будет сама переменная структуры в 100 Мб и в методе её точная копия ещё на 100 Мб и такой расход памяти уже можно будет ощутить.  Поэтому для таких случаев и можно использовать ключевое слово in — передать в метод только ссылку на область памяти где лежит значение и, при этом, запретить это значение изменять.

Подведем итог

Параметры в методы C# могут передаваться по значению и по ссылке. Если параметр передается по значению, то значение переменной, переданной в качестве параметра не изменяется так как в метод передается фактически её копия. В свою очередь, передавая параметр по ссылке, мы передаем в метод ссылку на память в которой находится значение параметра и, таким образом, можем изменять значение переменной, передаваемой в качестве параметра метода. Также, для параметров метода могут применяться модификаторы outи in. Выходные параметры метода (с ключевым словом out) могут не инициализироваться перед передаче в метод.

Домашнее задание №17

Разработайте метод Swap() который меняет местами значения двух целочисленных переменных.