Код в этой функции проходит в цикле все значения массива vals и суммирует их, возвращая получившийся результат. Мы вызываем эту функцию из Main() с пятью целыми параметрами:
int sum = sumVals (1, 5, 2, 9, 8) ;
Однако можно с тем же успехом вызвать эту функцию, передавая ей ноль, один, два или сто параметров целого типа: никаких ограничений на количество задаваемых параметров не существует.
Во всех предыдущих функциях применялись параметры, передаваемые по значению.Другими словами, мы передавали значение в переменную, которая затем использовалась внутри функции. Любые изменения, которые эта переменная претерпевала внутри функции, не оказывали никакого влияния на параметр, использованный при вызове функции. В качестве примера рассмотрим функцию, которая удваивает передаваемый ей параметр и выводит результат на экран:
static void showDouble(int val)
{
val *= 2;
Console.WriteLine(“val doubled = { 0 }” , val ) ;
}
В этой функции происходит удвоение передаваемого параметра. Если же мы вызовем эту функцию следующим образом:
int my Number = 5;
Console.WriteLine(“myNumber = {0}”, myNumber);
showDouble(myNumber) ;
Console.WriteLine(“myNumber = {0}”, myNumber);
то выходной поток, выведенный на консоль, будет таким:
Вызов функции showDouble() с переменной myNumber в качестве параметра не оказывает никакого влияния на переменную myNumber, описанную в Main () , несмотря на то, что параметр, которому присваивается ее значение, удваивается.
Если необходимо поменять значение переменной myNumber возникнет проблема. Конечно, можно воспользоваться функцией, которая возвращает новое значение переменной myNumber, и вызвать ее следующим образом:
int myNumber = 5;
Console.WriteLine(“myNumber = {0}”, myNumber);
myNumber = showDouble(myNumber);
Console.WriteLine(“myNumber = {0}”, myNumber);
Однако в таком коде довольно трудно разобраться; кроме того, такой способ не позволяет отразить изменения значений переменных, используемых в качестве параметров (поскольку функции всегда возвращают только одно значение). Вместо этого следует передавать параметр по ссылке.Это означает, что функция будет работать именно с той переменной, которая использовалась при вызове функции, а не с переменной, которая имеет то же значение. Следовательно, любые изменения переменной, использовавшейся функцией, отразятся на значении переменной, использовавшейся в качестве параметра. Для этого при описании параметра необходимо воспользоваться ключевым словом ref:
static void showDouble(ref int val)
{
val *= 2;
Console.WriteLine(“val doubled = {0}”, val);
}
Вторично ключевое слово ref необходимо использовать при вызове функции (это обязательное требование, поскольку тот факт, что параметр описан как ref, является неотъемлемой частью сигнатуры функции):
int myNumber = 5;
Console.WriteLine(“myNumber = {0}”, myNumber);
showDouble(ref myNumber);
Console.WriteLine(“myNumber = {0}”, myNumber);
В этом случае на консоль будет выведен следующий текст:
На этот раз переменная myNumber была изменена в функции showDouble ( ) .
Для переменных, используемых в качестве параметров типа ref, имеются два ограничения. Во-первых, поскольку существует вероятность, что в результате вызова функции значение вызываемого по ссылке параметра будет изменено, то при вызове функции запрещается использовать переменные типа const. Отсюда следует, что следующий вызов является недопустимым:
const int myNumber = 5;
Console.WriteLine(“mvNumber = {0}”, myNumber);
showDouble(ref myNumber);
Console.WriteLine(“myNumber = {0}”, myNumber);
Во-вторых, необходимо использовать заранее инициализированную переменную. С# не гарантирует, что параметр типа ref будет инициализирован той функцией, в которой он используется. Следующий код также является недопустимым:
int myNumber;
showDouble(ref myNumber);
Console.WriteLine(“myNumber = {0}”, myNumber);
В дополнение к возможности передавать параметры по ссылке можно указать, что данный параметр является выходным: в описание такого параметра включается ключевое слово out, используемое так же, как и ключевое слово ref (в качестве модификатора параметра в описании функции и при вызове функции). Фактически этот способ предоставляет почти такие же возможности, что и передача параметров по ссылке, в том смысле, что значение параметра после выполнения функции попадает в переменную, использовавшуюся при вызове этой функции. Имеются, однако, и существенные отличия. Хотя использовать переменную; которой не присвоено начальное значение, в качестве параметра типа ref недопустимо, она может применяться в качестве параметра типа out. Более того, параметр типа out будет рассматриваться как не имеющий начального значения самой функцией, в которой он используется. Это означает, что хотя передача переменной, которой присвоено некоторое значение, в качестве параметра типа out является допустимой, однако в процессе выполнения функции хранящееся в этой переменной значение будет утрачено.
В качестве примера рассмотрим расширение функции maxValue(), которая возвращает элемент массива с максимальным значением. Модифицируем эту функцию так, чтобы получать индекс элемента массива, содержащего наибольшее значение; в случаях, когда максимальное значение содержится в нескольких элементах, мы будем получать индекс первого максимального элемента. Для этого добавим выходной параметр:
static int MaxValue(int[] intArray, out int maxIndex)
{
int maxVal = intArray[0];
maxIndex = 0;
for (int i = 1; i < int Array. Length; i++)
{
if (intArray[i] > maxVal)
{
maxVal = intArray[i];
maxIndex = i;
}
}
return maxVal;
}
Эта функция может быть использована таким образом:
int[] myArray = {I, 8, 3, 6, 2, 5, 9, 3, 0, 2};
int maxlndex;
maxValue(myArray, out maxIndex));
Console.WriteLine(“The first occurrence of this value is at element {0}”,