Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

А теперь посмотрим, как в 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"
:

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
.

Использование модификатора params

В языке C# поддерживаются массивы параметров с использованием ключевого слова

params
, которое позволяет передавать методу переменное количество идентично типизированных параметров (или классов, связанных отношением наследования) в виде единственного логического параметра. Вдобавок аргументы, помеченные ключевым словом
params
, могут обрабатываться, когда вызывающий код передает строго типизированный массив или список элементов, разделенных запятыми. Да, это может сбивать с толку! В целях прояснения предположим, что вы хотите создать функцию, которая позволяет вызывающему коду передавать любое количество аргументов и возвращает их среднее значение.

Если вы прототипируете данный метод так, чтобы он принимал массив значений

double
, тогда в вызывающем коде придется сначала определить массив, затем заполнить его значениями и, наконец, передать его методу. Однако если вы определите метод
CalculateAverage
как принимающий параметр
params
типа
double[]
, то вызывающий код может просто передавать список значений
double
, разделенных запятыми. "За кулисами" список значений
double
будет упакован в массив типа
double
.

// Возвращение среднего из некоторого количества значений double.

static double CalculateAverage(params double[] values)

{

Console.WriteLine("You sent me {0} doubles.", values.Length);

double sum = 0;

if(values.Length == 0)

{

return sum;

}

for (int i = 0; i < values.Length; i++)

Поделиться с друзьями: