Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Podbelsky_V_V_C_Bazovy_kurs.pdf
Скачиваний:
69
Добавлен:
02.06.2015
Размер:
1.73 Mб
Скачать

144

Г л а в а 8

 

 

19.Как инициализировать массив строк?

20.Как получить строку, символы которой представляют значение типа long?

21.Какими средствами можно получить код значения базового типа, символьная запись которого находится в строке.

22.Как при запуске программы задать аргументы?

23.Как в теле программы получить аргументы из командной строки?

Методы C#

9.1. Методы-процедуры и методы-функции

Как писал Никлаус Вирт, программы — это алгоритмы + структуры данных. Данные в C# – это поля объектов и статические поля классов. Алгоритмы (т. е. функциональность программ) представляются с помощью методов класса и методов его объектов. В языке C# методы не существуют вне классов. Нестатические методы – реализуют функциональность объектов. Статические методы обеспечивают функциональность классов и тем самым программы в целом.

Для определения методов и при их вызове в C# не используются никакие служебные слова. В «языках древности», таких как Фортран или Кобол, и в некоторых более современных языках, не входящих в семейство Си-образных, для обозначения подпрограмм, функций, процедур используются специальные термины, включаемые в список служебных слов соответствующего языка. (FUNCTION, SUBROUTINE – в Фортране, procedure в Паскале и т.д.). Для вызова подпрограмм в Фортране используется конструкция со служебным словом CALL и т.п.

Вязыках, ведущих свое происхождение от языка Си (С++, Java, C# и др.) при определении функций и для обращения

кним специальные термины не применяются. Это в полной мере относится и к методам языка C#. Однако синтаксически и семантически методы C# можно разделить на процедуры и функции. Это деление не особенно жесткое и в ряде случаев метод может играть две роли – и процедуры и функции.

Вупрощенном варианте формат декларации метода, который может играть роль как процедуры, так и функции, можно представить так:

модификаторы_методаopt

тип_возвращаемого_значения имя_метода (спецификация_параметров)

{ операторы_тела_метода }

Индекс opt указывает на необязательность модификаторов метода.

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

Минимальная конструкция, применяемая для обращения к методу:

имя_метода(список_аргументов).

В общем случае имя метода при обращении дополняется префиксами, указывающими на принадлежность метода пространству имен, конкретному классу или реально существующему объекту.

Метод-процедура отличается от метода-функции следующими свойствами:

1.В качестве типа возвращаемого значения используется void, т.е. процедура не возвращает в точку вызова никакого результата.

2.В теле процедуры может отсутствовать оператор возврата

return, а когда он присутствует, то в нем нет выражения для вычисления возвращаемого значения. Если оператор return отсутствует, то точка выхода из процедуры (из метода) расположена за последним оператором тела метода.

3. Для обращения к методу-процедуре используется только оператор вызова метода:

имя_метода (список_аргументов);

Метод–функция:

1.В качестве типа возвращаемого значения используется тип ссылки или тип значения. Таким образом, функция всегда возвращает в точку вызова результат.

2.В теле функции всегда присутствует, по крайней мере, один оператор возврата:

return выражение;

Выражение определяет возвращаемый функцией результат. 3. Обращение к методу-функции может использоваться в качестве операнда подходящего выражения. Термин

«подходящего» относится к необходимости согласования операндов в выражении по типам.

Методы C#

147

 

 

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

имя_метода (список_аргументов);

В этом случае функция выступает в роли процедуры.

Когда вы знакомитесь с некоторым методом (или пишете свой метод), очень важно понимать, откуда метод берет (или будет брать) исходные данные и куда (и как) метод отправляет результаты своей работы.

Исходные данные могут быть получены:

1)через аппарат параметров метода;

2)как глобальные по отношению к методу;

3)от внешних устройств (потоки ввода, файловые потоки). Результаты метод может передавать:

1)в точку вызова как возвращаемое функцией значение;

2)в глобальные по отношению к методу объекты;

3)внешним устройствам (потоки вывода, файловые потоки);

4)через аппарат параметров метода.

Глобальными по отношению к методу объектами в C# являются статические поля класса, в котором метод определен, и поля (статические) других классов, непосредственный доступ к которым имеет метод. Обмены через глобальные объекты являются нарушением принципов инкапсуляции и обычно в реальных разработках запрещены или не рекомендуются.

Обмены со стандартными потоками ввода-вывода, поддерживаемые средствами класса Console, нам уже знакомы. Для организации обменов с файловыми потоками используются те средства библиотеки классов, которые мы еще не рассматривали. Сосредоточимся на особенностях обменов через аппарат параметров.

При определении метода в его заголовке размещается спецификация параметров (возможно пустая) – разделенная запятыми последовательность спецификаторов параметров. Каждый спецификатор имеет вид:

модификатор тип_параметра имя_параметра

Модификатор параметра может отсутствовать или имеет одну из следующих форм: ref, out, params.

148

Г л а в а 9

 

 

Ограничений на тип параметра не накладывается. Параметр может быть предопределенного типа (базовые типы, строки, object); перечислением; структурой; классом; массивом; интерфейсом; делегатом.

Имя параметра — это идентификатор, который выбирает программист – автор метода. Область видимости и время существования параметра ограничиваются заголовком и телом метода. Таким образом, параметры не видны и недоступны для кода, который не размещен в теле метода.

Стандарт C# отмечает существование четырех видов параметров: ●●параметры, передаваемые по значениям;

●●параметры, передаваемые по ссылкам (ref); ●●выходные параметры (out); ●●массив-параметр (params).

Параметры первых трех видов в Стандарте C# называют фиксированными параметрами. Спецификация фиксированного параметра включает необязательный модификатор ref или out, обозначение типа и идентификатор (имя параметра).

Список параметров представляет собой возможно пустую последовательность разделенных запятыми спецификаторов параметров, из которых только последний может быть массивомпараметром, имеющим модификатор params.

Модификаторы метода необязательны, но их достаточно много. Вот их список, пока без комментариев:

new, public, protected, internal, private, static, virtual, sealed, override, abstract, extern.

В данной главе мы будем рассматривать только методы классов (не объектов). В декларацию каждого метода класса входит модификатор static, и такой метод называют статическим методом класса.

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

// 09_01.cs Статические методы – процедура и

функция using System; class Program

{

static void print(string line)

Методы C#

149

 

 

{

Console.WriteLine("Длина строки: " + line.Length); Console.WriteLine("Значение строки: " + line);

}

static string change(string str)

{

char[] rev = str.ToCharArray(); Array.Reverse(rev);

return new string(rev);

}

static void Main()

{

string numbers = "123456789"; print(numbers);

numbers = change(numbers); print(numbers);

}

}

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

Длина строки: 9 Значение строки: 123456789 Длина строки: 9

Значение строки: 987654321

Вклассе Program три статических метода. Метод print() получает исходные данные в виде строки-параметра и выводит длину и значение этой строки. В точку вызова метод print() ничего не возвращает – это процедура.

Метод change() – это функция. Он получает в качестве параметра строку, формирует ее перевернутое значение и возвращает в точку вызова этот результат.

Вфункции Main() определена ссылка numbers на строку "123456789". В отдельном операторе вызван метод-процеду- ра print(numbers), который выводит сведения о строке, именованной ссылкой numbers. Затем та же ссылка использована

вкачестве аргумента метода-функции change(). Обращение к этому методу размещено в правой части оператора присваивания, поэтому возвращаемый методом change() результат становится новым значением ссылки numbers. Повторное обращение к методу print() иллюстрирует изменения.

150

Г л а в а 9

 

 

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);

}

}

Методы C#

151

 

 

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

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));

}

}

152

Г л а в а 9

 

 

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

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.

Методы C#

153

 

 

В качестве примера метода с параметрами, передаваемыми по ссылкам, часто рассматривают метод 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():

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]