Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CSBasicCourse2ndedPodbelsky / CSBasicCourse2ndedPodbelsky.rtf
Скачиваний:
27
Добавлен:
22.03.2016
Размер:
11.9 Mб
Скачать

9.2. Соотношение фиксированных параметров и аргументов

Чтобы объяснить возможности и особенности разных видов параметров,

начнём с того, что при обращении к методу каждый фиксированный параметр

замещается

некоторым

аргументом.

Соответствие

между

параметрами

и

замещающими их аргументами устанавливается по их взаимному расположению, то

есть параметры определены позиционно.

Аргумент "аргумент" , заменяющий фиксированный параметр, представляет

собой выражение, тип которого совпадает или может быть приведён к типу,

указанному в спецификации соответствующего параметра.

Для

параметра,

передаваемого

по

значению

"параметр:параметр,

передаваемый по значению" , при обращении к методу создаётся внутри метода

временный объект, которому присваивается значение аргумента. Имя параметра в

теле метода соотнесено с этим временным объектом и никак не связано с те

м

конкретным аргументом, который использован в обращении вместо параметра.

Операции, выполняемые в теле метода с участием такого параметра, действуют

только на временный объект, которому присвоено значение аргумента.

В Стандарте C# для иллюстрации независимости аргумента от изменений

параметра, передаваемого по значению, приведена следующая программа:

//09_02.cs – параметр, передаваемый по значению

using System;

class Program

{

static void F(int p)

{

p++;

Console.WriteLine("p = {0}", p);

}

static void Main( )

{

int a = 1;

Console.WriteLine("pre: a = {0}", a);

F(a);

Console.WriteLine("post: a = {0}", a);

}

}

Результат выполнения программы:

pre: a = 1

p=2

post: a = 1

Изменение параметра p в теле метода F( ) не повлияло на значение аргумента a.

Таким

образом,

как

иллюстрирует

приведённый

пример,

параметры,

передаваемые по значениям, служат для передачи данных в метод, но не позволяют

вернуть какую-либо информацию из метода.

В классе может быть любое количество статических методов, и они могут

беспрепятственно обращаться друг к другу. Покажем на примере какие при этом

появляются возможности.

Задача: написать функцию (метод), возвращающую значение минимального и

з

четырёх аргументов. Прямой путь – использовать в теле метода вложенные

условные операторы или условные выражения. Поступим по-другому – определим

вспомогательную функцию, которая возвращает минимальное значение одного из

двух параметров. Программа может быть такой:

//09_03.cs – вложенные вызовы функций

using System;

class Program

{

// Вспомогательная функция:

static double min2(double z1, double z2)

{

return z1 < z2 ? z1 : z2;

}

// функция возвращает минимальное из значений параметров:

static double min4(double x1, double x2, double x3, double x4)

{

return min2(min2(min2(x1, x2), x3), x4);

}

static void Main()

{

Console.WriteLine(min4(24,8,4,0.3));

}

}

Результат выполнения программы:

0.3

В данном примере оба статических метода min2( ) и min4( ) выступают в роли

функций. Обратите внимание на вложение обращений к функции min2() в операторе

return функции min4( ).

Чтобы метод мог с помощью параметров изменять внешние по отношению к

методу объекты, параметры должны иметь модификатор ref, то есть передаваться

по ссылке.

Для иллюстрации этой возможности модифицируем программу 09_02.cs –

снабдим параметр новой функции FR( ) модификатором ref.

// 09_04.cs - параметр-значение, передаваемый по ссылке

using System;

class Program

{

static void FR(ref int p)

{

p++;

Console.WriteLine("p = {0}", p);

}

static void Main()

{

int a = 1;

Console.WriteLine("pre: a = {0}", a);

FR(ref a);

Console.WriteLine("post: a = {0}", a);

}

}

Результат выполнения программы:

pre: a = 1

p=2

post: a = 2

После обращения к методу FR( ) значение внешней по отношению F( )

переменной a изменилось.

Обратите внимание, что аргумент, подставляемый на место передаваемого по

ссылке параметра, должен быть снабжён модификатором ref.

В качестве примера метода с параметрами, передаваемыми по ссылкам, часто

рассматривают метод swap( ), меняющий местами значения двух объектов,

адресованных аргументами. Рассмотрим чуть более сложную задачу – метод

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

Для демонстрации возможностей вспомогательных методов определим в том же

классе метод упорядочения двух переменных(программа 09_05.cs):

// Вспомогательный метод

static void rank2(ref int x, ref int y)

{

int m;

if (x > y)

{

m = x; x = y; y = m;

}

}

Метод rank2() играет роль процедуры – он в точку вызова ничего не

возвращает, так как тип возвращаемого значения void. Параметры – целочисленные

переменные, передаваемые по ссылкам. В теле метода объявлена вспомогательная

переменная int m. Она используется как промежуточный буфер при обмене

значений параметров x и y.

Имея приведённый метод, можно написать следующую процедуру, решающую

нашу задачу сортировки трёх переменных:

static void rank3(ref int x1, ref int x2, ref int x3)

{

rank2(ref x1, ref x2);

rank2(ref x2, ref x3);

rank2(ref x1, ref x2);

}

В теле метода rank3( ) его параметры используются в качестве аргументов при

обращениях к методу rank2( ). Процедура rank2( ) вызывается трижды,

последовательно сортируя значения, на которые указывают параметры x1, x2, затем

x2, x3 и затем x1, x2. Функция Main(), иллюстрирующая применение метода rank3():

static void Main()

{

int i = 85, j = 23, k = 56;

rank3(ref i, ref j, ref k);

Console.WriteLine("i={0}, j={1}, k={2}", i, j, k);

}

}

Результат выполнения программы:

i=23, j=56, k=85

Итак,

параметры,

передаваемые

по

ссылке

"параметр:параметры,

передаваемые по ссылке" , используются для изменения уже существующих

значений внешних по отношению к методу объектов.

Обратите внимание, что модификатор ref "модификатор: ref" используется не

только перед параметром, но и перед замещающим его аргументом. Особо отметим

,

что аргументом может быть только переменная (не константа и не выражение) того

же типа, что и параметр.

Console.WriteLine(rank3(ref 24, ref 8, ref 4)); //ошибка!

// ERROR - аргументы должны быть переменными!!!

Выходные параметры

"параметр:выходные параметры"

снабжаются

модификатором out и позволяют присвоить значения объектам вызывающего

метода даже в тех случаях, когда эти объекты значений ещё не имели.

Возникает вопрос – зачем нужен модификатор out "модификатор: out" , если

те же действия обеспечивает применение модификатора ref? Связано появление

модификатора

out

с

правилом

обязательной

инициализации

переменных.

Модификатор out "говорит" компилятору – «не обращай внимание на отсутствие

значения у переменной, которая использована в качестве аргумента», и компилятор

не выдаёт сообщения об ошибке. Однако эта переменная обязательно должна

получить конкретное значение в теле метода. В противном случае компилятор

зафиксирует ошибку. Ошибкой будет и попытка использования в теле метода

значения выходного параметра без присваивания ему значения.

Метод с выходными параметрами (имеющими модификаторы ref или out)

обычно выступает в роли процедуры. Хотя не запрещено такому методу возвращать

значение с помощью оператора return. Примером такого метода служит метод

TryPasre(), который мы уже использовали в примерах программ.

В качестве иллюстрации применения выходных параметров приведём метод,

возвращающий целую (int integer) и дробную (double fra) части вещественного

числа (double x). В функции Main( ) определим три переменных: double real –

исходное число, double dPart – дробная часть, int iPart – целая часть. Переменная

real инициализирована, переменные iPart, dPart не имеют значений до обращения к

методу.

//09_06.cs – параметры-результаты

using System;

class Program

{

// Метод возвращает значения целой и дробной частей

// вещественного параметра

static void fun(double x, out int integer, out double fra)

{

integer = (int)x;

fra = x - integer;

}

static void Main()

{

double real = 53.93;

double dPart;

Соседние файлы в папке CSBasicCourse2ndedPodbelsky