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

При передаче параметров по ссылке перед параметрами используется модификатор ref:

static void Main(string[] args)

{

int x = 10;

int y = 15;

Addition(ref x, y); // вызов метода

Console.WriteLine(x);

 

Console.ReadLine();

}

// определение метода

static void Addition(ref int x, int y)

{

x += y;

}

В чем отличие двух способов передачи параметров? При передаче по значению метод получает не саму переменную, а ее копию. А при передаче параметра по ссылке метод получает адрес переменной в памяти. И, таким образом, если в методе изменяется значение параметра, передаваемого по ссылке, то также изменяется и значение переменной, которая передается на его место. Например:

static void Main(string[] args)

{

//Начальные значения переменных a и b

int a = 5;

           int b = 6;

Console.WriteLine("Начальное значение переменной a = {0}", a);

//Передача переменных по значению

//После выполнения этого кода по-прежнему a = 5, так как мы передали лишь ее копию

AdditionVal(a, b);

Console.WriteLine("Переменная a после передачи по значению равна = {0}", a);

 

//Передача переменных по ссылке

//После выполнения этого кода a = 11, так как мы передали саму переменную

AdditionRef(ref a, b);

Console.WriteLine("Переменная a после передачи ссылке по значению равна = {0}", a);

Console.ReadLine();

}

// передача по ссылке

static void AdditionRef(ref int x, int y)

{

x = x + y;

Console.WriteLine("x + y = {0}", x);

}

// передача по значению

static void AdditionVal(int x, int y)

{

x = x + y;

Console.WriteLine("x + y = {0}", x);

}

Здесь в методе Main у нас есть две переменные: a и b. Имеется два метода, которые принимают два параметра: x и y. В обоих методах значение параметра x приравнивается сумме x и y.

В методе Main мы подставляем на место параметров x и y переменные a и b соответственно. В первом случае переменная передается по значению, то есть передается копия этой переменной, и она не изменяется. Во втором случае мы передаем указатель на эту переменную в памяти. И так как в методе AdditionRef значение параметра x изменяется, то передаваемая на его место переменная a тоже изменяет свое значение.

Обратите внимание, что модификатор ref указывается, как при объявлении метода, так и при его вызове в методе Main.

Модификатор out

Выше мы использовали входные параметры. Но параметры могут быть также выходными. Чтобы сделать параметр выходным, перед ним ставится модификатор out:

static void Sum(int x, int y, out int a)

{

a = x + y;

}

Здесь результат возвращается не через оператор return, а через выходной параметр. Использование в программе:

static void Main(string[] args)

{

int x = 10;

   

           int z;

               

           Sum(x, 15, out z);

   

           Console.WriteLine(z);

 

           Console.ReadLine();

}

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

Также обратите внимание, что методы, использующие такие параметры, обязательно должны присваивать им определенное значение. То есть следующий код будет недопустим, так как в нем для out-параметра не указано никакого значения:

static void Sum(int x, int y, out int a)

{

Console.WriteLine(x+y);

}

Прелесть использования подобных параметров состоит в том, что по сути мы можем вернуть из метода не один вариант, а несколько. Например:

static void Main(string[] args)

{

int x = 10;

int area;

int perimetr;

GetData(x, 15, out area, out perimetr);

Console.WriteLine("Площадь: " + area);

Console.WriteLine("Периметр: " + perimetr);

 

Console.ReadLine();

}

static void GetData(int x, int y, out int area, out int perim)

{

area= x * y;

perim= (x + y)*2;

}

Здесь у нас есть метод GetData, который, допустим, принимает стороны прямоугольника. А два выходных параметра мы используем для подсчета площади и периметра прямоугольника.

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

Стоит отметить, что в версии C# 7.0 (Visual Studio 2017) можно определять переменные в непосредственно при вызове метода. То есть вместо:

int x = 10;

int area;

int perimetr;

GetData(x, 15, out area, out perimetr);

Console.WriteLine("Площадь: " + area);

Console.WriteLine("Периметр: " + perimetr);

Мы можем написать:

int x = 10;

GetData(x, 15, out int area, out int perimetr);

Console.WriteLine("Площадь: " + area);

Console.WriteLine("Периметр: " + perimetr);

Необязательные параметры

C# позволяет использовать необязательные параметры. Для таких параметров нам необходимо объявить значение по умолчанию. Также следует учитывать, что после необязательных параметров все последующие параметры также должны быть необязательными:

static int OptionalParam(int x, int y, int z=5, int s=4)

{

return x + y + z + s;

}

Так как последние два параметра объявлены как необязательные, то мы можем один из них или оба опустить:

static void Main(string[] args)

{

OptionalParam(2, 3);

 

OptionalParam(2,3,10);

 

Console.ReadLine();

}

Именованные параметры

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

static int OptionalParam(int x, int y, int z=5, int s=4)

{

return x + y + z + s;

}

static void Main(string[] args)

{

OptionalParam(x:2, y:3);

               

           //Необязательный параметр z использует значение по умолчанию

OptionalParam(y:2,x:3,s:10);

 

Console.ReadLine();

}

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: