Содержание
Сегодня разберемся с тем, какие ключевые слова можно использовать в методах C#, в чем их различия, когда надо использовать in
, когда ref
или out
и так далее. Также затронем вопрос об использовании необязательных параметров в методах C#.
Зачем нужны ключевые слова in, out и ref?
Когда только-только начинаешь разбираться с языком программирования, то невольно возникают сотни различных вопросов. Например, зачем нам вообще нужны ключевые слова in
, out
и ref
в методах C#? Можно же просто передавать в метод определенные параметры и получать в ответ какие-то значения. Давайте рассмотрим простой пример. Допустим, пусть наш метод будет выполнять всего одну операцию — наращивать значение параметра на единицу и возвращать новое значение. Метод будет выглядеть у нас вот так:
static int Addition(int a) { a++; return a; }
Теперь вызовем наш метод в основной программе:
static void Main(string[] args) { Console.WriteLine("Введите любое целое число и нажмите Enter"); int a = int.Parse(Console.ReadLine()); Console.WriteLine($"Результат выполнения метода: {Addition(a)}. Значение переменной после выполнения метода: {a}"); }
Что выведет на экран наша программа. Смотрим:
1
Результат выполнения метода: 2.
Значение переменной после выполнения метода: 1
Как так? Мы же знаем, что арифметический оператор ++
наращивает значение переменной на 1
, но программа нам выдает, что переменная, которую мы передали в параметрах метода осталась неизменной, а результат — верный? На самом деле, здесь в метод мы передаем не саму переменную, а её копию. Значение копии увеличивается на 1 и возвращается нам, а сама переменная остается такой же какой и была. Такой способ передачи параметров называется передачей по значению.
Так вот, ключевые слова in
, out
и ref
в методах позволяют указать нам каким образом мы передаем параметры методу и, в зависимости от того, какое из ключевых слов мы указываем, компилятор и действует. Рассмотрим эти ключевые слова подробнее.
Ключевое слово ref
Ключевое слово ref
позволяет передавать аргумент (параметр) по ссылке, а не по значению. Если мы передаем параметр по ссылке, то этот параметр (переменную) можно изменить внутри метода, например, перепишем наш метод Addition
:
static int Addition(ref int a) { a++; return a; }
Теперь параметр a
передается по ссылке, значит внутри метода мы можем его изменить. Так как в описании метода мы использовали ключевое слово ref
, то и при вызове метода мы также должны использовать ref
при передаче параметров (обратите внимание на третью строку метода где вызывается Addition()
):
static void Main(string[] args) { Console.WriteLine("Введите любое целое число и нажмите Enter"); int a = int.Parse(Console.ReadLine()); Console.WriteLine($"Результат выполнения метода: {Addition(ref a)}. Значение переменной после выполнения метода: {a}"); }
Теперь результат работы программы будет следующий:
5
Результат выполнения метода: 6. Значение переменной после выполнения метода: 6
Как видите, передача параметра по ссылке позволяет изменять значение переменной в теле метода.
Ключевое слово out
Ключевое слово out
также используется для передачи аргументов (параметров) по ссылке. Оно похоже на ключевое слово ref
, за исключением того, что ref
требует инициализации переменной перед ее передачей. Например, если мы попробуем вызвать наш метод вот так:
int b; Addition(ref b);
то компилятор сообщит нам об ошибке:
так как переменная b
объявлена, но не инициализирована. С ключевым словом out
инициализацию переменной можно не проводить перед её передачей в метод и вот такой код не вызовет ошибки:
static int Addition(out int a) { a = 0;//присвоили начальное значение a++; //нарастил на 1 return a; } static void Main(string[] args) { int b; Console.WriteLine($"Результат выполнения метода: {Addition(out b)}. Значение переменной после выполнения метода: {b}"); }
Начиная с версии C# 7.0 переменные, передаваемые по ссылке, можно определять сразу в вызове метода, то есть вызов метода Addition()
в предыдущем примере можно переписать вот так:
Console.WriteLine($"Результат выполнения метода: {Addition(out int b)}. Значение переменной после выполнения метода: {b}");
Здесь мы сразу при вызове метода определили переменную b
.
Ключевое слово in
Кроме выходных параметров метода, объявляемых с модификатором out
, в C# можно также определить входные параметры, передаваемые по ссылке с использованием ключевого слова in
. Суть ключевого слова in
следующая — параметр с модификатором in
передается по ссылке, но внутри метода его изменять нельзя. Может возникнуть резонный вопрос: зачем нам тогда такой модификатор? Можно же просто убрать всякие ключевые слова и передавать параметр по значению. Как говориться, дьявол кроется в деталях.
Когда используется передача параметра по значению, то внутри метода создается точная копия переменной, когда по ссылке — в метод передается только адрес в памяти где лежит значение. Когда мы имеем дело с переменными простых типов, типа 5
, 2
, 99.9
, то особых проблем нет — на современных компьютерах мы даже не заметим, что программа «отъела»лишние байты памяти. А теперь представим, что в метод передается структура «весом» с сотню мегабайт. Передача по значению приведет к тому, что у нас в памяти будет сама переменная структуры в 100 Мб и в методе её точная копия ещё на 100 Мб и такой расход памяти уже можно будет ощутить. Поэтому для таких случаев и можно использовать ключевое слово in
— передать в метод только ссылку на область памяти где лежит значение и, при этом, запретить это значение изменять.
Итого
Итого, сегодня мы познакомились с ключевыми словами (модификаторами) для параметров методов: ref
, out
, in
и научились их использовать в зависимости от поставленных задач.