Так же, как и в случае команд, предназначенных для удаления символов, описываемые команды допускают вариант использования, позволяющий задавать символ, которым будет дополняться строка. В данном случае, однако, следует задавать отдельный символ, а не массив символов. Например:
myString = “Aligned”;
inyString = myString. PadLeft (10, ' -') ;
В итоге в начало строки, хранящейся в переменной myString, будет добавлено три символа тире.
3.3. Вопросы для повторения
1. Преобразование переменных из одного типа в другой.
2. Явные и неявные преобразования типов.
3. Сложные типы переменных.
4. Перечислимый тип, его определение и использование.
5. Структуры, их определение и использование.
6. Массивы: одномерные и многомерные.
7. Цикл foreach.
8. Строки, действия над строками.
Все программы до этого момента имели форму единого блока, в ряде случаев включавшем циклы, позволяющие многократно выполнять отдельные строки кода, и ветвление, позволяющее выполнять некоторые операторы по условию. Если возникала необходимость выполнить какую-либо операцию над данными, то нужный код должен был находиться там, где он будет работать.
Однако такая структура кода весьма ограниченна. Довольно часто возникают ситуации, когда выполнение определенных задач – например, поиск максимального элемента массива – необходимо в различных местах программы. Конечно, можно размещать идентичные (или почти идентичные) участки кода в разных частях приложения каждый раз, когда в этом возникает необходимость, однако такой подход имеет свои недостатки. Изменение даже одной небольшой детали, касающейся выполнения общей задачи (например, исправление некоторой ошибки), потребует внесения изменений во многих местах, возможно, разбросанных по всему приложению, а размер таких приложений бывает очень большим. Пропуск одного места может привести к непоправимым последствиям и неверному использованию всего приложения.
Решением такого рода проблем является применение функций. Функции в С# – это средство, позволяющее выполнять некоторые участки кода в произвольном месте приложения.
Функции особого типа, которые мы будем рассматривать в настоящей лекции, известны под названием методов. Однако при программировании в среде .NET этот термин имеет особое значение, которое станет понятным по мере изучения, поэтому на данный момент мы будем избегать его использования.
Например, можно написать функцию, которая осуществляет поиск максимального элемента массива. В результате появится возможность использовать эту функцию из произвольной точки программы, причем в каждом случае будут выполняться одни и те же строки кода. Поскольку мы должны написать этот код только один раз, то изменения, которые потребуется в него внести, повлияют на все вычисления, где бы этот код ни использовался. Такую функцию можно представить себе как повторно используемый код.
Функции также обладают тем преимуществом, что они позволяют делать программу более удобочитаемой, и мы получаем возможность группировать вместе логически связанные между собой части программ. Поступая таким образом, можно сделать тело самого приложения небольшим, поскольку решение внутренних задач приложения будет осуществляться отдельно. Это напоминает способ, посредством которого в VS можно соединять различные участки кода, используя режим схематического просмотра программ (outline view), что позволяет придать приложению более логичную структуру.
Функции могут также использоваться для создания многоцелевых программ, которые выполняют одни и те же операции над различными данными. Мы имеем возможность передавать функциям информацию, с которой они должны работать, в виде параметров и получать результаты работы функции в виде возвращаемых значений. В приведенном выше примере можно передать функции в качестве параметра массив, в котором осуществляется поиск, и получить элемент массива с максимальным значением в качестве возвращаемого значения. Отсюда следует, что мы можем каждый раз использовать одну и ту же функцию для работы с различными массивами. Параметры и возвращаемое значение функции вместе называются сигнатурой функции.
4.1.Описание и использование функций
В данном разделе рассказывается, каким образом можно включать функции в состав приложений, а затем использовать (вызывать) их из кода. Сначала будут рассмотрены простые функции, не обменивающиеся данными с вызывающим их кодом, а затем мы перейдем к более сложному использованию функций. Рассмотрим следующий пример. class Classl {
static void Write()
{
Console.WriteLine("Text output from function.");
}
static void Main(string[] args) { Write(); } }
Как это работает
Следующие две строки кода описывают простую функцию с именем Write (): static void Write () {
Console.WriteLine("Text output from function."); }
Код, содержащийся в данной функции, просто выводит некоторый текст в консольном окне. Однако это не столь важно, поскольку в настоящий момент нас в большей степени интересуют механизмы, лежащие в основе описания и использования функции.
В данном случае описание функции состоит из:
- двух ключевых слов: static и void;
- имени функции, за которым располагаются параметры: Write();
- участка выполняемого кода, заключенного в фигурные скобки;
Код, который используется для описания функции Write(), выглядит почти так же, как и код самого приложения: static void Main(string[] args) {}
Это объясняется тем, что весь код, который мы создавали до сих пор (не считая описания типов), представляет собой часть некоторой функции. Эта функция – Main() – выполняет (как упоминалось в первой лекции) функцию точки входа в консольное приложение. Когда запускается приложение, написанное на С#, то происходит вызов содержащейся в нем функции точки входа, а когда эта функция заканчивает свою работу, выполнение приложения прерывается. Любой выполняемый код, написанный на С#, должен иметь точку входа.
Единственное отличие между функцией Main() и функцией Write() (не считая тех строк кода, которые в них содержатся) заключается в том, что в круглых скобках, расположенных за именем функции Main, находится некоторый код. Этот код служит для задания параметров; к более подробному его обсуждению мы вернемся несколько позже.
Как уже упоминалось ранее, обе функции – и Main(), и Write() – описываются с использованием ключевых слов static (статический) и void (отсутствует). Ключевое слово static имеет отношение к понятиям объектно-ориентированного программирования и его рассмотрение отложим. На данном этапе от требуется запомнить только то, что все функции, которые будут задействованы в приложениях данного раздела, обязательно должны использовать это ключевое слово.
Ключевое слово void, напротив, объяснить очень просто. Оно указывает, что функция не возвращает никакого значения. Далее в этой лекции будет рассказано, что необходимо писать в тех случаях, когда у функции имеется возвращаемое значение.
Продолжая рассматривать наше приложение, мы обнаруживаем код, который осуществляет вызов функции Write().
Он состоит из имени функции, за которым помещаются пустые круглые скобки. Когда выполнение программы достигнет этой точки, начнет выполняться код, содержащийся в функции Write().
Следует обратить внимание, что использование круглых скобок как при описании функции, так и при ее вызове является обязательным.
4.2.Возвращаемые значения
Самый простой способ обмена данными с функциями – использование возвращаемого значения. Функции, в которых применяются возвращаемые значения, точно так же обладают численным значением, как и любые переменные, используемые при вычислении выражений. Аналогично переменным возвращаемые значения обладают типом.
Например, можно описать функцию с именем getString(), возвращаемое значение которой будет иметь тип string, и использовать ее в своей программе:
string myString; | |
myString = getString() |
;
С другой стороны, можно описать функцию с именем getVal(), которая будет возвращать значение типа double, и использовать ее в математическом выражении:
double myVal; | ||
double multiplier =5.3; | ||
myVal = getVal() * multiplier |
;
Если функция должна обладать возвращаемым значением, то необходимо внести два изменения:
- в описании функции вместо ключевого слова void указать тип возвращаемого значения;
- по завершении всех вычислений в функции использовать ключевое слово return и передать возвращаемое значение вызывающему коду.
Синтаксис кода для рассматриваемого типа функций консольного приложения будет выглядеть следующим образом:
static <возвращаемыйТип> <имяФуккции>() { return <возвращаемоеЗначение>; }
Единственным ограничением в данном случае является требование, гласящее, что <возвращаемоеЗначение> должно иметь тип <возвращаемыйТип> или же должна существовать возможность его неявного преобразования в этот тип.
Вообще говоря, <возвращаемыйТип> может быть любым, включая самые сложные типы из числа рассмотренных ранее. В простейшем случае это может выглядеть следующим образом: static double getVal() { return 3.2; }
Однако в реальной жизни возвращаемые значения обычно являются продуктом выполняемых функцией некоторых вычислений, поскольку того же результата можно достигнуть простым использованием переменной типа const.
Когда при выполнении программы достигается оператор return, управление немедленно передается обратно в вызывающий код. Никакие строки кода после этого оператора выполняться не будут. Отсюда, однако, совершенно не следует, что в теле функции оператор return обязательно должен быть последним. Он может быть использован и раньше, например, при ветвлении по какому-либо условию. Включение оператора return в цикл for, в блок if или в какую-нибудь другую структуру приведет к немедленному окончанию выполнения как этой структуры, так и всей функции в целом.