Скачиваний:
74
Добавлен:
24.03.2015
Размер:
300.54 Кб
Скачать

Глава 9. Методы с#

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

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

Для определения методов и при их вызове в С# не используются никакие служебные слова. В "языках древности", таких как ФОРТРАН или КОБОЛ, и в некоторых более современных языках, не входящих в семейство Си-образных, для обозначения подпрограмм, функций, процедур используются специальные термины, включаемые в список служебных слов соответствующего языка. (FUNCTION, SUBROUTINE - в Фортране, procedure в Паскале и т.д.). Для вызова подпрограмм в Фортране используется конструкция со служебным словом CALL и т.п.

В языках, ведущих своё происхождение от языка Си (C++, Java, C# и др.) при определении функций и для обращения к ним специальные термины не применяются. Это в полной мере относится и к методам языка С#. Однако синтаксически и семантически методы С# можно разделить на процедуры и функции. Это деление не особенно жёсткое и в ряде случаев метод может играть две роли - и процедуры и функции.

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

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

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

Индекс opt указывает на необязательность модификаторов метода. Фигурные скобки ограничивают тело метода, часть объявления перед телом метода называют заголовком метода. Минимальная конструкция, применяемая для обращения к методу:

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

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

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

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

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

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

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

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

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

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

return выражение;

Выражение определяет возвращаемый функцией результат.

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

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

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

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

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

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

  1. Через аппарат параметров метода;

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

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

Результаты метод может передавать:

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

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

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

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

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

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

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

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

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

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

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

Стандарт С# отмечает существование четырёх видов параметров:

  • параметры, передаваемые по значениям;

  • параметры, передаваемые по ссылкам (ref);

  • выходные параметры (out);

  • массив-параметр (params).

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

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

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

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

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

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

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

static void print(string line)

{

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() иллюстрирует изменения.

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