Книга: Microsoft Visual C#. Подробное руководство. 8-е издание
Назад: 2. Работа с переменными, операторами и выражениями
Дальше: 4. Использование инструкций принятия решений

3. Создание методов и применение областей видимости

Прочитав эту главу, вы научитесь:

объявлять и вызывать методы;

передавать методу информацию;

возвращать информацию из метода;

определять локальную область видимости и область видимости класса;

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

В главе 2 «Работа с переменными, операторами и выражениями» вы узнали, как объявляются переменные, как с использованием операторов создаются выражения и как на способ вычисления выражений, содержащих несколько операторов, влияют приоритетность и ассоциативность. В этой главе будут изу­чаться методы. Будет показано, как объявляются и вызываются методы, как для передачи методу информации используются аргументы и параметры и как с помощью инструкции return из метода возвращается информация. Вы также увидите, как с помощью встроенного отладчика Microsoft Visual Studio 2015 осуществляется пошаговое выполнение кода внутри и за пределами методов. Эта информация вам пригодится, если методы станут работать неожиданным образом и возникнет необходимость проведения трассировки их выполнения. И наконец, вы научитесь объявлять методы, получающие дополнительные параметры, и вызывать методы путем использования поименованных аргументов.

Создание методов

Метод представляет собой именованную последовательность инструкций. Если вам уже приходилось заниматься программированием на таких языках, как C, C++ или Microsoft Visual Basic, то вы поймете, что метод похож на функцию или подпрограмму. У метода есть имя и тело. Имя метода должно представлять собой идентификатор со смысловым значением, указывающим на общую цель метода (например, для метода, вычисляющего налог на прибыль, можно выбрать имя calculateIncomeTax). Тело метода содержит инструкции, выполняемые при его запуске. Кроме этого, методам могут передаваться данные для обработки, а также методы могут возвращать информацию, которая обычно является результатом их работы. Методы являются основным и весьма эффективным механизмом языка.

Объявление метода

Для объявления метода в C# используется следующий синтаксис:

returnType methodName ( parameterList )

{

    // тело метода, куда помещаются инструкции

}

Объявление состоит из следующих элементов:

• returnType — это название типа, указывающее на разновидность информации, возвращаемой методом в качестве результата его работы. Указываться может любой тип, например int или string. Если создается метод, не возвращающий информацию, то вместо типа возвращаемого значения нужно использовать ключевое слово void (пустой);

• methodName — это имя, используемое для вызова метода. Имена методов следуют тем же правилам идентификации, что и имена переменных. Например, addValues является приемлемым именем метода, а add$Values — нет. Впредь для назначения имен методам вам нужно будет следовать соглашению о смешанном регистре (camelCase), например displayCustomer;

• parameterList — это необязательный список, описывающий типы и имена элементов информации, которые могут передаваться в метод для их обработки. Параметры записываются между открывающей и закрывающей круглыми скобками, ( ), в таком же виде, как и при объявлении переменных, с названием типа, за которым следует имя параметра. Если у создаваемого метода имеется два и более параметра, их нужно отделять друг от друга запятыми;

• инструкций тела метода, которые представляют собой строки кода, запускаемые при вызове метода. Они заключены между открывающей и закрывающей фигурными скобками, { }.

174817.png

ВНИМАНИЕ Если вам уже приходилось программировать на C, C++ и Visual Basic, то вы могли заметить, что глобальные методы в C# не поддерживаются. Все методы нужно создавать внутри класса, в противном случае ваш код не пройдет компиляцию.

Рассмотрим определение метода по имени addValues, возвращающего результат типа int и имеющего два int-параметра, leftHandSide и rightHandSide:

int addValues(int leftHandSide, int rightHandSide)

{

    // ...

    // тело метода, куда помещаются инструкции

    // ...

}

173290.png

ПРИМЕЧАНИЕ Тип любого параметра, а также тип возвращаемого методом значения нужно указывать явным образом. Ключевое слово var использовать нельзя.

Рассмотрим определение метода по имени showResult, не возвращающего значение и имеющего всего один параметр типа int под названием answer:

void showResult(int answer)

{

    // ...

}

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

174824.png

ВНИМАНИЕ Если вы знакомы с Visual Basic, то должны заметить, что в C# не используются разные ключевые слова, отличающие метод, возвращающий значение (функцию), от метода, не возвращающего значение (от процедуры или подпрограммы). В C# следует указывать либо тип возвращаемого значения, либо ключевое слово void.

Возвращение данных из метода

Если нужно, чтобы метод возвращал информацию (то есть чтобы тип его возвращаемого значения не обозначался как void), вы должны включить в тело метода в конце обработки данных инструкцию return. Эта инструкция состоит из ключевого слова return, за которым следуют выражение, определяющее возвращаемое значение, и ставится точка с запятой. Тип выражения должен совпадать с типом, указанным при объявлении метода. Например, если метод возвращает значение типа int, значит, инструкция return должна возвращать int, в противном случае ваша программа не откомпилируется. Рассмотрим пример метода с инструкцией return:

int addValues(int leftHandSide, int rightHandSide)

{

    // ...

    return leftHandSide + rightHandSide;

}

Обычно инструкция return размещается в конце метода, поскольку она заставляет метод завершить работу и вернуть управление инструкции, вызвавшей метод, о чем будет рассказано далее. Любые инструкции, оказавшиеся после инструкции return, не выполняются (если инструкции помещены после инструкции return, компилятор выдает соответствующее предупреждение).

Если методу не нужно возвращать информацию (то есть его тип возвращаемого значения обозначен как void), можно воспользоваться вариантом инструкции return, вызывающим немедленный выход из метода. При этом сразу же после ключевого слова return следует поставить точку с запятой, например:

void showResult(int answer)

{

    // вывод на экран ответа

    Console.WriteLine($"The answer is {answer}");

    return;

}

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

Использование метода-выражения

Некоторые методы могут быть очень простыми, выполняющими только одну задачу или возвращающими результаты вычисления без применения какой-либо дополнительной логики. Для методов, содержащих только одно выражение, в C# поддерживается упрощенная форма. Также эти методы могут принимать параметры и возвращать значения и работают точно так же, как методы, с которыми вы уже знакомы. В следующих примерах кода показаны упрощенные версии методов addValues и showResult, записанные в виде методов-выражений:

int addValues(int leftHandSide, int rightHandSide) => leftHandSide + rightHandSide;

void showResult(int answer) => Console.WriteLine($"The answer is {answer}");

Основное отличие от обычных методов состоит в использовании для ссылки на выражение, формирующее тело метода, оператора => и в отсутствии инструкции return. В качестве возвращаемого значения используется значение выражения, а если выражение не возвращает значение, значит, метод объявляется с использованием ключевого слова void.

Функционально между использованием обычного метода и метода-выражения нет никакой разницы, последний из них — это не более чем синтаксическое соглашение. Но далее в книге будут приводиться примеры, в которых методы-выражения позволят четче выразить суть программы, освобождая ее от множества ненужных символов { и } и упрощая чтение кода.

В следующем упражнении будет исследована еще одна версия проекта MathsOperators из главы 2. Эта версия была усовершенствована за счет разумного использования ряда небольших методов. Такой способ разбиения кода упрощает его понимание и дальнейшее сопровождение.

Исследование определений методов

Откройте в среде Visual Studio 2015 проект Methods, который находится в папке \Microsoft Press\VCSBS\ Chapter 3\Methods вашей папки документов.

Щелкните в меню Отладка на пункте Начать отладку. Среда Visual Studio 2015 проведет сборку и запуск приложения. Его внешний вид должен быть таким же, как и у приложения из главы 2. Ознакомьтесь еще раз с приложением и порядком его работы, а затем вернитесь в Visual Studio. Щелкните в меню Отладка на пункте Остановить отладку.

Выведите в окно редактора код файла MainPage.xaml.cs (для этого в обозревателе решений раскройте узел MainPage.xaml, а затем дважды щелкните на имени файла MainPage.xaml.cs). Найдите метод addValues, который должен иметь следующий вид:

private int addValues(int leftHandSide, int rightHandSide)\

{

    expression.Text = $"{leftHandSide} + {rightHandSide}";

    return leftHandSide + rightHandSide;

}

173296.png

ПРИМЕЧАНИЕ Пусть присутствие ключевого слова private в начале определения этого метода вас пока не смущает; о том, что оно означает, вы узнаете при изучении главы 7 «Создание классов и объектов и управление ими».

Метод addValues содержит две инструкции. Первая из них показывает производимое вычисление в имеющемся в форме поле выражения, вторая использует int-версию оператора + для сложения int-переменных leftHandSide и rightHandSide, а затем возвращает результат этой операции. Вспомним, что сложение двух int-значений создает еще одно int-значение, следовательно, типом возвращаемого методом addValues значения будет int.

Если изучить методы subtractValues, multiplyValues, divideValues и remain­derValues, можно увидеть, что в них используется похожая схема.

Найдите в окне редактора метод showResult, имеющий следующий вид:

private void showResult(int answer) => result.Text = answer.ToString();

Это метод-выражение, выводящий на экран, в имеющееся в форме поле результата, строку, представляющую собой параметр answer. Он не возвращает значение, поэтому для него указан тип void.

175072.png

СОВЕТ Минимальной длины метода не существует. Если метод позволяет избавиться от повторений и облегчает понимание программы, его следует признать полезным, каким бы он ни был коротким.

Нет и максимальной длины метода, но обычно применительно к выполняемой задаче код метода стараются сделать как можно короче. Если код вашего метода не помещается на экран монитора, подумайте о возможности его разбиения на более мелкие методы, чтобы их было легче читать.

Вызов методов

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

Определение синтаксиса вызова метода

Синтаксис вызова метода выглядит в C# следующим образом:

result = methodName ( argumentList )

Рассмотрим описание элементов, составляющих вызов метода.

• Элемент methodName должен в точности соответствовать имени вызываемого метода. При этом нужно помнить, что язык C# чувствителен к регистру символов.

• Элемент result = необязательный. Если он указан, переменная с идентификатором result будет содержать значение, возвращенное методом. Если это void-метод (то есть метод, не возвращающий значение), элемент инструкции result = следует опустить. Если для метода, возвращающего значение, не указать result =, метод запустится, но возвращаемое значение останется неиспользованным.

• Элемент argumentList предоставляет информацию, принимаемую методом. Каждому параметру нужно предоставить аргумент, а значение каждого аргумента должно быть совместимо с типом соответствующего ему параметра. Если у вызываемого метода несколько параметров, аргументы должны отделяться друг от друга запятыми.

174830.png

ВНИМАНИЕ Круглые скобки нужно включать в каждый вызов метода, даже если у метода нет аргументов.

Чтобы разъяснить эти положения, рассмотрим метод addValues еще раз:

int addValues(int leftHandSide, int rightHandSide)

{

    // ...

}

У метода addValues имеется два параметра типа int, следовательно, его нужно вызвать с указанием двух отделенных друг от друга запятой аргументов, имеющих тип int:

addValues(39, 3); // все правильно

Можно также заменить буквальные значения 39 и 3 именами int-переменных. Затем значения этих переменных передаются методу в качестве его аргументов:

int arg1 = 99;

int arg2 = 1;

addValues(arg1, arg2);

Если попытаться вызвать addValues каким-нибудь другим способом, то, скорее всего, попытка будет безуспешной по причинам, раскрытым в следующих примерах:

addValues;            // ошибка в ходе компиляции, отсутствуют круглые скобки

addValues();          // ошибка в ходе компиляции, недостаточно аргументов

addValues(39);        // ошибка в ходе компиляции, недостаточно аргументов

addValues("39", "3"); // ошибка в ходе компиляции, неверные типы аргументов

Метод addValues возвращает значение, имеющее тип int. Это int-значение можно применить там, где такое значение используется. Рассмотрим следующие примеры:

int result = addValues(39, 3); // в правой части присваивания

showResult(addValues(39, 3));  // в качестве аргумента вызова другого метода

В следующем упражнении будет продолжена работа с приложением Methods. На этот раз будут исследованы вызовы метода.

Исследование вызовов метода

Вернитесь в проект Methods. Выведите в окно редактора код файла MainPage.xaml.cs. Найдите метод calculateClick и посмотрите на первые две инструкции этого метода после инструкции try и открывающей фигурной скобки. (Инструкции try будут рассматриваться в главе 6 «Обработка ошибок и исключений».) Они имеют следующий вид:

int leftHandSide = System.Int32.Parse(lhsOperand.Text);

int rightHandSide = System.Int32.Parse(rhsOperand.Text);

Эти две инструкции объявляют две int-переменные с именами leftHandSide и rightHandSide. Обратите внимание на способ их инициализации. В обоих случаях вызывается метод Parse структуры System.Int32. (System является пространством имен, а Int32 — именем структуры в этом пространстве имен. О структурах вы узнаете в главе 9 «Создание типов значений с использованием перечислений и структур».) Ранее вам уже встречался этот метод, он получает один строковый параметр и преобразует его в int-значение. Эти две строки кода получают то, что пользователь набрал в имеющихся в форме текстовых полях lhsOperand и rhsOperand, и преобразуют эти значения в тип int.

Посмотрите на четвертую инструкцию метода calculateClick (после инструкции if и еще одной открывающей фигурной скобки):

calculatedValue = addValues(leftHandSide, rightHandSide);

Эта инструкция вызывает метод addValues, передавая ему в качестве аргументов значения переменных leftHandSide и rightHandSide. Значение, возвращаемое методом addValues, сохраняется в переменной calculatedValue.

Посмотрите на следующую инструкцию:

showResult(calculatedValue);

Она вызывает метод showResult, передавая ему в качестве аргумента значение переменной calculatedValue. Метод showResult никакого значения не возвращает.

Найдите в окне редактора рассмотренный ранее метод showResult. В нем содержится всего одна инструкция:

result.Text = answer.ToString();

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

175078.png

СОВЕТ Методы, принадлежащие другим объектам, можно вызывать, указывая в качестве префикса имя объекта. В предыдущем примере выражение answer.ToString() вызывает метод по имени ToString, принадлежащий объекту по имени answer.

Применение области видимости переменных

Переменные создаются для хранения значений. Их можно создавать в различных местах вашего приложения. Например, в методе calculateClick проекта Methods создается int-переменная по имени calculatedValue и ей присваивается начальное значение 0:

private void calculateClick(object sender, RoutedEventArgs e)

{

    int calculatedValue = 0;

...

}

Эта переменная начинает свое существование в том месте, где она определена, после чего следующие инструкции в методе calculateClick могут ее использовать. Важный момент: переменная может использоваться только после ее создания. Когда метод завершает свою работу, эта переменная исчезает и уже не может где-либо использоваться.

Когда к переменной имеется доступ в конкретном месте программы, говорится, что переменная в этом месте находится в области видимости. Область видимости переменной calculatedValue ограничивается методом, к ней можно получить доступ в пространстве метода calculateClick, но не за его пределами. Можно также определить переменные с другой областью видимости, например за пределами метода, но внутри класса, и доступ к этим переменным можно получить из любого метода внутри этого класса. Про такие переменные говорят, что их областью видимости является пространство класса.

Иначе говоря, область видимости переменной — это просто участок программы, в пределах которого переменной можно воспользоваться. Область видимости имеется не только у переменных, но и у методов. Далее вы узнаете, что область видимости идентификатора (переменной или метода) привязана к месту объявления, вводящего идентификатор в программу.

Определение локальной области видимости

Область видимости внутри метода определяют открывающая и закрывающая фигурные скобки, формирующие его тело. Любые переменные, объявленные внутри тела метода, обладают областью видимости в его пределах и исчезают, как только метод завершает свою работу. Они могут быть доступны только коду, выполняемому в этом методе. Такие переменные называются локальными, поскольку они имеют локальную привязку к методу, в котором объявлены, и не находятся в области видимости любого другого метода.

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

class Example

{

    void firstMethod()

    {

        int myVar;

        ...

    }

    void anotherMethod()

    {

        myVar = 42; // ошибка – такая переменная в области видимости отсутствует

        ...

    }

}

Этот код не будет откомпилирован, поскольку метод anotherMethod пытается использовать переменную myVar, не находящуюся в его области видимости. Переменная myVar доступна только инструкциям в методе firstMethod, следующим в нем после строки, объявляющей myVar.

Определение области видимости внутри класса

Область видимости внутри класса определяют открывающая и закрывающая фигурные скобки, формирующие тело этого класса. Любые переменные, объявленные внутри тела класса (но не внутри метода), имеют область видимости в пределах этого класса. В C# для переменной, определенной классом, применяется термин поле. Как уже упоминалось, в отличие от локальных переменных, поля можно использовать для обмена информацией между методами. Рассмотрим следующий пример:

class Example

{

    void firstMethod()

    {

        myField = 42; // ok

        ...

    }

    void anotherMethod()

    {

        myField++; // ok

        ...

    }

    int myField = 0;

}

Переменная myField определена в классе, но за пределами методов firstMethod и anotherMethod. Поэтому областью видимости myField является класс, и эту переменную можно использовать в любых методах данного класса.

Применительно к примеру следует отметить еще одно обстоятельство. В методе переменная должна быть объявлена до ее применения. Поля в этом плане несколько отличаются. Метод может использовать поле до той инструкции, в которой это поле определяется, — все тонкости этого обстоятельства улаживаются компилятором.

Перегрузка методов

Если у двух идентификаторов одинаковые имена и они объявлены в одной и той же области видимости, то к ним применяется понятие перегрузка. Зачастую перегрузка идентификатора является ошибкой, отлавливаемой в ходе компиляции. Например, если в одном и том же методе объявляются две локальные переменные с одинаковыми именами, компилятор выдает ошибку. Аналогично, если в одном и том же классе объявляются два поля с одинаковыми именами или два одинаковых метода, будет получена ошибка в ходе компиляции. Казалось бы, зачем об этом говорить, учитывая, что все пока что превращалось в ошибку в ходе компиляции. Но существует весьма полезный и важный способ, позволяющий перегрузить идентификатор для метода.

Рассмотрим метод WriteLine класса Console. Вы уже им пользовались для вывода строки на экран. Но в процессе написания кода C# при наборе WriteLine в окне редактора кода и текста можно заметить, что механизм Microsoft IntelliSense дает вам в виде подсказки 19 различных вариантов! Каждая версия метода WriteLine получает разный набор параметров: одна вообще не получает параметров и просто выводит пустую строку, другая получает булев параметр и выводит строку, представляющую его значение (True или False), а еще одна реализация получает параметр в виде десятичного числа и выводит его в виде строки и т.д. В процессе работы компилятор смотрит на типы передаваемых вами аргументов, а затем подстраивается под ваше приложение для вызова той версии метода, которая соответствует имеющемуся набору параметров. Рассмотрим пример:

static void Main()

{

    Console.WriteLine("The answer is ");

    Console.WriteLine(42);

}

В первую очередь перегрузка пригодится тогда, когда нужно будет выполнить одну и ту же операцию над данными различных типов или при различных вариантах группировки информации. Вы можете перегрузить метод, когда различные реализации имеют разные наборы параметров, то есть когда имеется одно и то же имя, но разное количество параметров или когда различаются типы этих параметров. При вызове метода ему предоставляется список аргументов, отделенных друг от друга запятыми, а количество и тип аргументов используются компилятором для выбора одного из вариантов перегружаемых методов. Но следует иметь в виду, что, несмотря на возможность перегрузки, связанной с параметрами метода, вы не можете выполнить перегрузку, исходя из типа возвращаемого методом значения. Иными словами, нельзя объявить два метода с одним и тем же именем, которые отличались бы друг от друга только типом возвращаемого ими значения. (Компьютер, конечно, устройство умное, но не до такой же степени.)

Создание методов

В следующих упражнениях будет создан метод, вычисляющий сумму, которую получит консультант за заданное количество консультационных дней при фиксированной посуточной ставке. Сначала будет разработана логика приложения, а затем задействован мастер создания заглушек для методов — Generate Method Stub Wizard, помогающий создавать методы, используемые этой логикой. Далее, чтобы разобраться в работе программы, вы запустите эти методы в консольном приложении. И наконец, воспользуетесь отладчиком Visual Studio 2015, чтобы выполнить код в пошаговом режиме внутри вызываемого метода и за его пределами.

Разработка логики для приложения

Откройте в Visual Studio 2015 проект DailyRate, который находится в папке \Microsoft Press\VCSBS\Chapter 3\DailyRate вашей папки документов. Зайдите в обозреватель решений и в проекте DailyRate дважды щелкните на файле Program.cs, чтобы код для программы отобразился в окне редактора. Эта программа является простым стендом для проверки работоспособности кода. Когда приложение приступает к работе, оно вызывает метод run. Вы добавляете к методу run тот код, чью работу хотите опробовать. (Способ вызова метода требует знаний о том, что такое классы, а этот вопрос будет рассматриваться в главе 7.)

Добавьте к телу метода run между открывающей и закрывающей фигурными скобками следующие инструкции, выделенные жирным шрифтом:

void run()

{

    double dailyRate = readDouble("Enter your daily rate: ");

    int noOfDays = readInt("Enter the number of days: ");

    writeFee(calculateFee(dailyRate, noOfDays));

}

Блок кода, только что добавленный к методу run, вызывает метод readDouble (который вскоре будет создан), чтобы спросить у пользователя, какова дневная ставка консультанта. Следующая инструкция вызывает метод readInt (который также вскоре будет создан), чтобы получить количество дней. И наконец, вызывается метод writeFee (который также еще не создан) с целью вывода результата на экран. Обратите внимание на то, что значение, передаваемое методу writeFee, является значением, возвращенным методом calculateFee (это последний намеченный к созданию метод), который получает дневную ставку и количество дней и вычисляет сумму подлежащего к выплате заработка.

173302.png

ПРИМЕЧАНИЕ Методы readDouble, readInt, writeFee и calculateFee пока еще не созданы, поэтому IntelliSense при наборе данного кода их не показывает. Не пытайтесь выполнять сборку приложения на этом этапе — у вас ничего не получится.

Создание методов с помощью мастера заглушек Generate Method Stub Wizard

Найдите в окне редактора, в методе run, вызов метода readDouble и щелкните на нем правой кнопкой мыши. Появится контекстное меню, содержащее команды, необходимые для создания и редактирования кода (рис. 3.1).

03_01_NEW.tif 

Рис. 3.1

Щелкните в этом меню на пункте Быстрые действия (Quick Actions).

Visual Studio удостоверится в том, что метод readDouble не существует, и покажет мастер, позволяющий создать заглушку для этого метода. Visual Studio исследует вызов метода readDouble, установит тип его параметров и тип возвращаемого значения и предложит исходную реализацию этого метода (рис. 3.2).

03_02.tif 

Рис. 3.2

Щелкните на пункте Создайте метод "Program.readDouble" (Generate Method 'Program.readDouble'). Среда Visual Studio добавит к вашему коду следующий метод:

private double readDouble(string v)

{

    throw new NotImplementedException();

}

Новый метод создан с классификатором private, который будет рассмотрен в главе 7. Пока в теле метода просто выдается исключение NotImplementedException. (Исключения рассматриваются в главе 6.) Далее вы замените это тело своим собственным кодом.

Удалите инструкцию throw new NotImplementedException(); из метода readDouble, заменив ее следующими строками кода, выделенными жирным шрифтом:

private double readDouble(string v)

{

    Console.Write(v);

    string line = Console.ReadLine();

    return double.Parse(line);

}

Этот блок кода выводит на экран строку, находящуюся в переменной v. Эта переменная является строковым параметром, передаваемым при вызове метода, и предлагает пользователю ввести посуточную ставку.

173312.png

ПРИМЕЧАНИЕ Метод Console.Write похож на инструкцию Console.WriteLine, которая использовалась в предыдущих упражнениях, и отличается только тем, что не выводит после сообщения символ новой строки.

Пользователь набирает значение, которое считывается в строку с помощью метода ReadLine и преобразуется в значение числа с двойной точностью, для чего применяется метод double.Parse. Результат передается назад в качестве возвращаемого значения вызываемого метода.

173318.png

ПРИМЕЧАНИЕ Метод ReadLine является методом-компаньоном для WriteLine, он считывает пользовательский ввод с клавиатуры, завершающийся нажатием клавиши Ввод. Текст, набранный пользователем, передается назад в виде возвращаемого значения. Текст возвращается в виде строкового значения.

Щелкните в методе run правой кнопкой мыши на вызове метода readInt, после этого щелкните на пункте Быстрые действия, а затем на пункте Создайте метод "Program.readInt".

Будет создан метод readInt:

private int readInt(string v)

{

    throw new NotImplementedException();

}

Замените инструкцию throw new NotImplementedException(); в теле метода readInt следующим кодом, выделенным жирным шрифтом:

private int readInt(string v)

{

    Console.Write(v);

    string line = Console.ReadLine();

    return int.Parse(line);

}

Этот блок кода похож на код для метода readDouble. Единственная разница заключается в том, что этот метод возвращает значение типа int, следовательно, строка, набранная пользователем, преобразуется в число, для чего используется метод int.Parse.

Щелкните правой кнопкой мыши на вызове метода calculateFee, после этого щелкните на пункте Быстрые действия, а затем на пункте Создайте метод "Program.calculateFee".

Будет создан метод calculateFee:

private object calculateFee(double dailyRate, int noOfDays)

{

    throw new NotImplementedException();

}

Обратите внимание на то, что в данном случае Visual Studio для создания имен параметров использует имена переданных методу аргументов. (Разумеется, вы можете изменить имена параметров, если они вам не подходят.) Еще более интригующим является выбор типа, возвращаемого методом, который указывается как object. Среда Visual Studio не может точно определить тип значения, которое должно быть возвращено методом из того контекста, в котором он вызван. Тип object просто означает нечто, и вы при добавлении в метод кода должны изменить его на требуемый тип. Более подробно тип object рассматривается в главе 7.

Измените определение метода calculateFee таким образом, чтобы он, как показано в этом коде жирным шрифтом, возвращал значение в виде числа с двойной точностью:

private double calculateFee(double dailyRate, int noOfDays)

{

    throw new NotImplementedException();

}

Замените тело метода calculateFee и переделайте его в метод-выражение со следующим выражением, выделенным жирным шрифтом. Эта инструкция вычисляет подлежащий выплате заработок путем перемножения двух параметров:

private double calculateFee(double dailyRate, int noOfDays) => dailyRate *

noOfDays;

Щелкните правой кнопкой мыши на вызове метода writeFee, находящемся в методе run, щелкните на пункте Быстрые действия, а затем на пункте Создайте метод "Program.writeFee".

Обратите внимание: среда Visual Studio, чтобы выяснить, что его параметр должен принадлежать типу double, использует определение метода writeFee. Кроме того, в вызове метода не используется возвращаемое значение, поэтому для него объявляется тип void:

private void writeFee(double v)

{

    ...

}

175084.png

СОВЕТ Если вы хорошо разбираетесь в синтаксисе, то можете создавать методы, набирая их в окне редактора. Постоянно использовать пункт меню Создайте… вас никто не заставляет.

Замените код в теле метода writeFee следующей инструкцией, которая выводом результата на экран вычисляет заработок и добавляет 10 % комиссии. Еще раз обратите внимание на то, что теперь это не просто метод, а метод-выражение:

private void writeFee(double v) => Console.WriteLine($"The consultant's fee is:

{v * 1.1}");

Щелкните в меню Сборка на пункте Собрать решение.

Реорганизация кода

Весьма полезной особенностью Visual Studio 2015 является возможность реорганизации кода.

Временами вы станете замечать, что создаете один и тот же или очень похожий код более чем в одном месте приложения. Когда это произойдет, выделите только что набранный блок кода, щелкните на нем правой кнопкой мыши, после чего щелкните на пункте Быстрые действия, а затем на пункте Извлечение метода (Extract Method). Выбранный код будет перемещен в новый метод по имени NewMethod. Мастер извлечения метода способен также определить, должен ли метод принимать какие-либо параметры и иметь возвращаемое значение. После создания метода нужно изменить его имя на что-либо более понятное, вписав его поверх прежнего, а также изменить инструкцию, созданную для вызова этого метода, вписав в нее новое имя.

Тестирование программы

Щелкните в меню Отладка на пункте Запуск без отладки (Start Without Debugging). Среда Visual Studio 2015 проведет сборку программы, а затем запустит ее на выполнение. Появится окно консоли. В строке приглашения ввести посуточную ставку Enter Your Daily Rate наберите 525 и нажмите Ввод. В строке приглашения ввести количество дней Enter The Number of Days наберите 17 и нажмите Ввод.

Программа выведет в окно консоли следующее сообщение о подлежащем выплате заработке:

The consultant's fee is: 9817,5

Нажмите Ввод, чтобы закрыть приложение и вернуться в среду Visual Studio 2015.

В следующем упражнении для прогона программы в медленном темпе будет использован отладчик Visual Studio 2015. Вы увидите, что происходит, когда вызывается каждый метод (это называется шагом с заходом в метод), а затем увидите, как каждая инструкция return передает управление назад вызывавшей инструкции (это называется шагом с выходом из метода). При шаге с заходом в метод и при шаге с выходом из метода вы сможете воспользоваться инструментами, имеющимися на панели отладки. Когда приложение запущено в режиме отладки, те же самые команды доступны и в меню Отладка.

Пошаговое выполнение методов с использованием отладчика Visual Studio 2015

Найдите в окне редактора метод run. Поставьте курсор на первую инструкцию этого метода:

double dailyRate = readDouble("Enter your daily rate: ");

Щелкните правой кнопкой мыши в любом месте этой строки, а затем щелкните на пункте Выполнить до текущей позиции (Run To Cursor).

Программа запустится и будет выполняться, пока не дойдет до первой инструкции в методе run, после чего встанет на паузу. Текущая инструкция будет помечена желтой стрелкой в левом поле окна редактора, а сама инструкция будет выделена желтым фоном (рис. 3.3).

Выберите в меню Вид пункт Панели инструментов (Toolbars) и убедитесь, что слева от пункта Отладка (Debug toolbar) установлен флажок. Когда он установлен, панель инструментов отладки будет открыта. Эта панель может быть пристыкована к другим панелям инструментов. Если вы не сможете ее найти, попробуйте воспользоваться командой Панели инструментов в меню Вид, чтобы скрыть эту панель (снять флажок), и посмотрите, какие кнопки исчезнут. Затем снова выведите панель на экран. Панель инструментов отладки имеет следующий вид (рис. 3.4).

Щелкните на панели инструментов отладки на кнопке Шаг с заходом (Step Into) (это шестая кнопка слева). Отладчик сделает шаг с заходом в вызываемый метод. Желтый курсор переместится на открывающую фигурную скобку в начале метода readDouble.

03_03.tif 

Рис. 3.3

03_04.tif 

Рис. 3.4

Щелкните еще раз на кнопке Шаг с заходом, чтобы курсор переместился на первую инструкцию:

Console.Write(v);

175091.png

СОВЕТ Вместо повторных щелчков на кнопке Шаг с заходом на панели отладки можно нажимать клавишу F11.

Щелкните на панели отладки на кнопке Шаг с обходом (Step Over) (это седьмая кнопка слева). Метод выполнит следующую инструкцию без ее отладки (без шага с заходом в нее). Такое действие может пригодиться в том случае, если инструкция вызывает метод, но вы не хотите вызывать пошаговое выполнение каждой его инструкции. Желтый курсор переместится на вторую инструкцию метода, и программа перед возвращением в Visual Studio 2015 выведет в окно консоли приглашение на ввод посуточной ставки. (Окно консоли может скрываться за окном Visual Studio.)

175098.png

СОВЕТ Вместо того чтобы щелкать на кнопке Шаг с обходом на панели отладки, можно нажимать клавишу F10.

Еще раз щелкните на панели отладки на кнопке Шаг с обходом. На этот раз желтый курсор исчезнет и активируется окно консоли, поскольку программа выполняет метод Console.ReadLine и ожидает, что вы что-нибудь наберете в строке приглашения. Наберите в окне консоли 525 и нажмите Ввод.

Управление вернется в Visual Studio 2015. Желтый курсор появится на третьей строчке метода.

Наведите указатель мыши на имя переменной line во второй или в третьей строке метода (неважно, в какой именно). Появится подсказка, выводящая текущее значение переменной line ("525"). Это позволяет убедиться в том, что при пошаговом выполнении кода метода переменной было присвоено ожидаемое вами значение (рис. 3.5).

03_05.tif 

Рис. 3.5

Щелкните на панели отладки на кнопке Шаг с выходом (Step Out) (это восьмая кнопка слева). Запустится непрерывное выполнение кода метода до самого конца. Работа метода readDouble завершится, и желтый курсор вернется к первой инструкции метода run. Теперь эта инструкция завершит свою работу.

175103.png

СОВЕТ Вместо того чтобы щелкать на кнопке Шаг с выходом на панели отладки, можно нажимать комбинацию клавиш Shift+F11.

Щелкните на панели отладки на кнопке Шаг с заходом. Желтый курсор переместится на вторую инструкцию метода run:

int noOfDays = readInt("Enter the number of days: ");

Щелкните на панели отладки на кнопке Шаг с обходом. На этот раз выбран запуск метода без пошагового выполнения кода внутри него. Снова появится окно консоли с приглашением на ввод количества дней. Наберите в окне консоли 17 и нажмите Ввод. Управление будет возвращено Visual Studio 2015 (возможно, придется вывести эту среду на первый план). Желтый курсор переместится на третью инструкцию метода run:

writeFee(calculateFee(dailyRate, noOfDays));

Щелкните на панели отладки на кнопке Шаг с заходом. Желтый курсор перейдет на выражение, определяющее тело метода calculateFee. Этот метод будет вызван раньше метода writeFee, поскольку значение, которое им возвращается, метод writeFee использует в качестве параметра.

Щелкните на панели отладки на кнопке Шаг с выходом. Вызов метода calculateFee завершится, и желтый курсор вернется обратно на третью инструкцию метода run.

Щелкните на панели отладки на кнопке Шаг с заходом. На этот раз желтый курсор перейдет на инструкцию, определяющую тело метода writeFee. Поставьте в определении метода указатель мыши над параметром v. В экранной подсказке будет показано значение v, равное 8925.

Щелкните на панели отладки на кнопке Шаг с выходом. В окне консоли появится сообщение The consultant's fee is: 9817,5. (Если окно консоли скрыто за окном Visual Studio 2015, его нужно вывести на первый план.) Желтый курсор вернется на третью инструкцию в методе run.

Щелкните на панели инструментов на кнопке Продолжить (Continue), чтобы заставить программу продолжить выполнение без остановок на каждой инструкции.

175109.png

СОВЕТ Если кнопка Продолжить не видна, щелкните на раскрывающемся меню Добавить или удалить кнопки (Add Or Remove Buttons), которое появляется в конце панели отладки, а затем выберите пункт Продолжить. После этого должна появиться кнопка Продолжить. Вместо этого для продолжения выполнения приложения без отладки можно нажать клавишу F5.

Приложение выполнится до конца и завершит работу. Обратите внимание на то, что с окончанием работы приложения исчезнет и инструментальная панель отладчика, поскольку при исходных настройках она отображается только при запуске приложения в режиме отладки.

Использование необязательных параметров и именованных аргументов

Вы уже видели, как путем определения перегружаемых методов можно реализовать разные версии метода, получающего различные параметры. При создании приложения, использующего перегружаемые методы, компилятор определяет, какие конкретные экземпляры каждого метода нужно использовать для удовлетворения каждого вызова. Это общая черта многих объектно-ориентированных языков, присущая не только C#. Но для создания Windows-приложений и компонентов разработчики могут использовать другие языки, которые не придерживаются этих правил. Основной особенностью C# и других языков, разработанных для среды .NET Framework, является возможность взаимодействия с приложениями и компонентами, написанными с применением других технологий. Одной из важнейших технологий, положенных в основу многих Windows-приложений и служб, работающих вне среды .NET Framework, является объектная модель компонентов (Component Object Model (COM)). По сути, общеязыковая среда выполнения (common language runtime (CLR)), используемая .NET Framework, так же сильно зависит от применения COM, как и среда выполнения Windows Runtime операционной системы Windows 10. В COM не поддерживаются перегружаемые методы, вместо этого в ней используются методы, способные принимать необязательные параметры. Чтобы упростить использование COM-библиотек и компонентов в решении на C#, язык C# также поддерживает необязательные параметры.

Необязательные параметры могут пригодиться и в других ситуациях. Они предоставляют компактные и простые решения при невозможности использования перегружаемых методов по причине несущественных различий типов параметров, не позволяющих компилятору заметить разницу между реализациями. Рассмотрим, к примеру, следующий код:

public void DoWorkWithData(int intData, float floatData, int moreIntData)

{

    ...

}

Метод DoWorkWithData принимает три параметра: два типа int и один типа float. Теперь предположим, что вам нужно предоставить реализацию метода DoWorkWithData, принимающего только два параметра: intData и floatData. Можно перегрузить метод:

public void DoWorkWithData(int intData, float floatData)

{

    ...

}

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

int arg1 = 99;

float arg2 = 100.0F;

int arg3 = 101;

 

DoWorkWithData(arg1, arg2, arg3); // Вызов перегружаемого метода с тремя

                                     параметрами

DoWorkWithData(arg1, arg2);       // Вызов перегружаемого метода с двумя

                                     параметрами

Но предположим, что вам понадобилось реализовать две дополнительные версии DoWorkWithData, принимающие только первый и третий параметры. Можно попытаться сделать следующее:

public void DoWorkWithData(int intData)

{

    ...

}

public void DoWorkWithData(int moreIntData)

{

    ...

}

Проблема здесь в том, что компилятору эти два перегружаемых метода представляются совершенно идентичными. Ваш код не пройдет компиляцию, и будет выдана ошибка, говорящая о том, что тип с таким-то названием уже определяет экземпляр по имени DoWorkWithData с такими же типами параметров. Чтобы разобраться в случившемся, подумайте, что бы произошло, будь этот код допустимым. Рассмотрим следующие инструкции:

int arg1 = 99;

int arg3 = 101;

 

DoWorkWithData(arg1);

DoWorkWithData(arg3);

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

Определение необязательных параметров

Отсылка на необязательность параметра делается при определении метода предоставлением параметру исходного значения. Это значение указывается путем использования оператора присваивания. В показанном далее методе optMethod первый параметр является обязательным, поскольку для него не указано исходное значение, а вот второй и третий параметры являются необязательными:

void optMethod(int first, double second = 0.0, string third = "Hello")

{

    ...

}

Сначала должны быть указаны все обязательные и только потом — любые необязательные параметры.

Вызов метода, принимающего необязательные параметры, можно осуществлять тем же способом, что и вызов любого другого метода: нужно указать имя метода и предоставить любые необходимые аргументы. Отличие методов, принимающих необязательные параметры, состоит в том, что соответствующие этим параметрам аргументы можно опустить, и тогда при запуске метод воспользуется исходным значением. В следующем примере при первом вызове метода optMethod ему предоставляются значения для всех трех параметров. При втором вызове указываются только два аргумента, и эти значения применяются для первого и второго параметров. Третий параметр получает при запуске метода исходное значение "Hello":

optMethod(99, 123.45, "World"); // Аргументы предоставлены всем трем параметрам

optMethod(100, 54.321);         // Аргументы предоставлены только первым двум

                                   параметрам

Передача именованных аргументов

Изначально C# использует позицию каждого аргумента в вызове метода для определения того, к какому параметру какой аргумент применить. Поэтому второй пример метода OptMethod, показанный в предыдущем разделе, передает два аргумента параметрам метода first и second, поскольку таков порядок их появления в объявлении метода. C# позволяет также указывать параметры по именам. Это свойство позволяет передавать аргументы в другой последовательности. Для передачи аргумента в качестве именованного параметра указывается имя параметра, затем ставится двоеточие и указывается используемое значение. Следующие примеры выполняют ту же самую функцию, что и показанные в предыдущем разделе, за исключением того, что параметры указаны по имени:

optMethod(first : 99, second : 123.45, third : "World");

optMethod(first : 100, second : 54.321);

Именованные аргументы дают возможность передавать аргументы в любом порядке. Код вызова метода optMethod можно переписать следующим образом:

optMethod(third : "World", second : 123.45, first : 99);

optMethod(second : 54.321, first : 100);

Это свойство позволяет также опускать аргументы. Например, при вызове метода optMethod можно указать значения только для первого и третьего параметров, а для второго параметра воспользоваться его исходным значением:

optMethod(first : 99, third : "World");

Кроме того, позиционные и именованные аргументы можно смешивать. Но если использовать этот технический прием, то перед первым именованным аргументом нужно указать все позиционные аргументы:

optMethod(99, third : "World"); // Сначала указан позиционный аргумент

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

Применение необязательных параметров и именованных аргументов может привести к некоторой неоднозначности вашего кода. Стоит разобраться с тем, как компилятор разрешает эти неоднозначности, иначе в приложениях может обнаружиться неожиданное поведение. Предположим, что вы определили метод optMethod в качестве перегружаемого, как показано в следующем примере:

void optMethod(int first, double second = 0.0, string third = "Hello")

{

    ...

}

void optMethod(int first, double second = 1.0, string third = "Goodbye",

     int fourth = 100 )

{

    ...

}

Это абсолютно допустимый код C#, который следует правилам для перегружаемых методов. Компилятор может отличить один метод от другого, поскольку у них разные списки параметров. Но как показано в следующем примере, при вызове метода optMethod и пропуске некоторых аргументов, соответствующих одному или нескольким необязательным параметрам, может возникнуть проблема:

optMethod(1, 2.5, "World");

Это опять же вполне допустимый код, но какой из версий метода optMethod он будет выполняться? Ответ таков: той, которая больше соответствует вызову метода. Следовательно, код вызовет тот метод, который получает три, а не четыре параметра. Имеет смысл рассмотреть следующий пример:

optMethod(1, fourth : 101);

В этом примере в вызове optMethod не указаны аргументы для второго и третьего параметров, а аргумент для четвертого параметра указан по имени. Этому вызову соответствует только одна версия optMethod, следовательно, проблемы не возникнет. А вот следующий пример заставит вас призадуматься:

optMethod(1, 2.5);

На этот раз точного соответствия предоставленному списку аргументов нет ни у одного из вариантов метода optMethod. Обе его версии имеют необязательные параметры для второго, третьего и четвертого аргументов. Тогда какую из версий вызовет эта инструкция: ту, которая примет три параметра и воспользуется при этом исходным значением для третьего из них, или ту, которая примет четыре параметра и воспользуется при этом исходным значением для третьего и четвертого? Ответ будет следующим: ни ту ни другую. Это неразрешимая неоднозначность, и компилятор не позволит скомпилировать приложение. Сходная ситуация с тем же результатом возникает при попытках вызова метода optMethod в любой из показанных далее инструкций:

optMethod(1, third : "World");

optMethod(1);

optMethod(second : 2.5, first : 1);

В заключительном упражнении этой главы вы попрактикуетесь в реализации методов, принимающих необязательные параметры, и их вызове с использованием именованных аргументов. А также протестируете типовые примеры разрешения компилятором C# вызовов, использующих необязательные параметры и именованные аргументы.

Определение и вызов метода, принимающего необязательные параметры

Откройте в среде Visual Studio 2015 проект DailyRate, который находится в папке \Microsoft Press\VCSBS\Chapter 3\DailyRate Using Optional Parameters вашей папки документов. Раскройте в обозревателе решений проект DailyRate и дважды щелкните на имени файла Program.cs для отображения кода программы в окне редактора. Эта версия приложения не содержит ничего, кроме метода Main и структурной версии метода run.

В классе Program после метода run добавьте метод calculateFee. Это та же самая версия метода, которая была создана в предыдущем наборе упражнений, за исключением того, что она принимает два необязательных параметра с исходными значениями. Метод также выводит сообщение, показывающее версию вызванного метода calculateFee. (Перегружаемые реализации этого метода будут добавлены в дальнейшем.)

private double calculateFee(double dailyRate = 500.0, int noOfDays = 1)

{

    Console.WriteLine("calculateFee using two optional parameters");

    return dailyRate * noOfDays;

}

Добавьте к классу Program еще одну реализацию метода calculateFee, имеющую код, показанный далее. Эта версия принимает один необязательный параметр по имени dailyRate типа double. Тело метода вычисляет и возвращает сведения о заработке, причитающемся только за один день:

private double calculateFee(double dailyRate = 500.0)

{

    Console.WriteLine("calculateFee using one optional parameter");

 

    int defaultNoOfDays = 1;

    return dailyRate * defaultNoOfDays;

    }

Добавьте к классу Program третью реализацию метода calculateFee. Эта версия не принимает параметры и использует зафиксированные в ней значения для посуточной ставки и количества дней:

private double calculateFee()

{

    Console.WriteLine("calculateFee using hardcoded values");

    double defaultDailyRate = 400.0;

    int defaultNoOfDays = 1;

    return defaultDailyRate * defaultNoOfDays;

    }

Добавьте в метод run следующие инструкции, выделенные жирным шрифтом, которые вызывают calculateFee и показывают результат:

public void run()

{

    double fee = calculateFee();

    Console.WriteLine($"Fee is {fee}");

}

175114.png

СОВЕТ Определение метода можно быстро просмотреть из вызывающей его инструкции. Для этого щелкните правой кнопкой мыши на вызове метода, а затем на пункте Показать определение (Peek Definition). Появляющееся после этого окно с определением метода calculateFee показано на рис. 3.6.

03_06.tif 

Рис. 3.6

Это свойство принесет особую пользу, если ваш код разбит на несколько файлов или находится в одном, но слишком длинном файле.

Щелкните в меню Отладка на пункте Запуск без отладки, чтобы выполнить сборку и запуск программы. Она запустится в окне консоли и выведет следующее сообщение:

calculateFee using hardcoded values

Fee is 400

Метод run вызвал версию calculateFee, не принимающую параметры, а не те реализации, которые принимают необязательные параметры, поскольку именно эта версия больше всех подходит вызову метода. Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в среду Visual Studio.

Измените в методе run инструкцию, вызывающую calculateFee, чтобы она приняла вид, выделенный ниже жирным шрифтом:

public void run()

{

    double fee = calculateFee(650.0);

    Console.WriteLine($"Fee is {fee}");

}

Щелкните в меню Отладка на пункте Запуск без отладки, чтобы выполнить сборку и запуск программы. Будет выведено следующее сообщение:

calculateFee using one optional parameter

Fee is 650

На этот раз метод run вызвал версию calculateFee, принимающую один необязательный параметр. Как и прежде, эта версия больше остальных подходила вызову метода. Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в среду Visual Studio.

Еще раз измените в методе run инструкцию, вызывающую calculateFee:

public void run()

{

    double fee = calculateFee(500.0, 3);

    Console.WriteLine($"Fee is {fee}");

}

Щелкните в меню Отладка на пункте Запуск без отладки, чтобы выполнить сборку и запуск программы. Будет выведено следующее сообщение:

calculateFee using two optional parameters

Fee is 1500

Как и при двух предыдущих запусках, метод run ожидаемо вызвал версию calculateFee, принимающую два необязательных параметра. Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в среду Visual Studio.

Измените в методе run инструкцию, вызывающую calculateFee, указав параметр dailyRate по имени:

public void run()

{

    double fee = calculateFee(dailyRate : 375.0);

    Console.WriteLine($"Fee is {fee}");

}

Щелкните в меню Отладка на пункте Запуск без отладки, чтобы выполнить сборку и запуск программы. Будет выведено следующее сообщение:

calculateFee using one optional parameter

Fee is 375

Метод run опять вызвал версию calculateFee, принимающую один необязательный параметр. Изменение кода для использования именованного аргумента не привело к изменению способа принятия компилятором решения о том, какую версию метода вызывать в этом примере. Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в среду Visual Studio.

Измените в методе run инструкцию, вызывающую calculateFee, указав по имени параметр noOfDays:

public void run()

{

    double fee = calculateFee(noOfDays : 4);

    Console.WriteLine($"Fee is {fee}");

}

Щелкните в меню Отладка на пункте Запуск без отладки, чтобы выполнить сборку и запуск программы. Будет выведено следующее сообщение:

calculateFee using two optional parameters

Fee is 2000

На этот раз метод run вызвал версию calculateFee, принимающую два необязательных параметра. В вызове метода был опущен первый параметр (dailyRate) и указан по имени второй. Этому вызову соответствовала только одна версия метода calculateFee, принимающая два необязательных параметра. Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в среду Visual Studio.

Измените реализацию метода calculateFee, принимающего два необязательных параметра. Измените имя первого параметра на theDailyRate и обновите инструкцию return, чтобы она соответствовала тому, что в следующем коде выделено жирным шрифтом:

private double calculateFee(double theDailyRate = 500.0, int noOfDays = 1)

{

    Console.WriteLine("calculateFee using two optional parameters");

    return theDailyRate * noOfDays;

}

Измените в методе run инструкцию, вызывающую calculateFee, указав параметр theDailyRate по имени:

public void run()

{

    double fee = calculateFee(theDailyRate : 375.0);

    Console.WriteLine("Fee is {fee}");

}

Щелкните в меню Отладка на пункте Запуск без отладки, чтобы выполнить сборку и запуск программы. Будет выведено следующее сообщение:

calculateFee using two optional parameters

Fee is 375

В прошлый раз, когда указывалась посуточная ставка, но не указывалось количество дней, метод run вызывал версию calculateFee, принимающую один необязательный параметр. В этот раз метод run вызвал версию calculateFee, принимающую два необязательных параметра. В данном случае использование именованного аргумента изменило способ принятия компилятором решения о том, какую из версий метода нужно вызвать. Если указывается именованный аргумент, компилятор сравнивает имя аргумента с именами параметров, указанными при объявлении метода, и выбирает метод, имеющий параметр с соответствующим именем. Если бы в вызове метода calculateFee аргумент был указан как aDailyRate: 375.0, программа не была бы откомпилирована, потому что ни у одной из версий метода нет параметра, соответствующего этому имени. Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в среду Visual Studio.

Выводы

В данной главе вы узнали, как определяются методы для реализации именованного блока кода. Вам было показано, как в методы передаются параметры и как из методов возвращаются данные. Вы также увидели, как вызывается метод, передаются аргументы и получается возвращаемое значение. Вы узнали, как определяются перегружаемые методы с различными списками параметров, и увидели, как область видимости переменных определяет, где к ним можно обращаться. Затем вы воспользовались отладчиком Visual Studio 2015 для пошагового выполнения кода. И наконец, узнали, как создаются методы, принимающие необязательные параметры, и как вызываются методы с использованием именованных аргументов.

Если хотите продолжить работу и изучить следующую главу, оставьте открытой среду Visual Studio 2015 и переходите к главе 4 «Использование инструкций принятия решений».

Если хотите выйти из среды Visual Studio 2015, то в меню Файл щелкните на пункте Выход. Если увидите диалоговое окно с предложением сохранить изменения, щелкните на кнопке Да и сохраните проект.

Краткий справочник

Чтобы

Сделайте следующее

Объявить метод

Напишите метод внутри класса. Укажите имя метода, список параметров и тип возвращаемого значения, затем создайте тело метода, заключив его в фигурные скобки, например:

int addValues(int leftHandSide, int rightHandSide)

{

   ...

}

Возвратить значение из метода

Напишите внутри метода инструкцию return, например:

return leftHandSide + rightHandSide;

Вернуться из метода до его окончания

Напишите инструкцию return внутри метода, например:

return;

Определить метод-выражение

Воспользуйтесь последовательностью символов =>, указав после нее выражение, определяющее тело метода, и поставив закрывающую точку с запятой, например:

double calculateFee(double dailyRate, int noOfDays)=> dailyRate * noOfDays;

Вызвать метод

Напишите имя метода, за которым укажите в круглых скобках любые аргументы, например:

addValues(39, 3);

Воспользоваться мастером создания методов-заглушек (Generate Method Stub Wizard)

Щелкните правой кнопкой мыши на вызове метода, а затем щелкните на пункте Создайте метод

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

Выберите в меню Вид пункт Панели инструментов и установите флажок слева от пункта Отладка

Сделать шаг с заходом в метод

Щелкните на панели отладки на кнопке Шаг с заходом или щелкните в меню Отладка на пункте Шаг с заходом

Сделать шаг с выходом из метода

Щелкните на панели отладки на кнопке Шаг с выходом или щелкните в меню Отладка на пункте Шаг с выходом

Указать методу необязательный параметр

Предоставьте исходное значение для параметра в объявлении метода, например:

void optMethod(int first, double second = 0.0,

string third = "Hell"»)

{

  ...

}

Передать методу именованный аргумент

Укажите имя параметра в вызове метода, например:

optMethod(first : 100, third : "World");

Назад: 2. Работа с переменными, операторами и выражениями
Дальше: 4. Использование инструкций принятия решений

Антон
Перезвоните мне пожалуйста 8(812)642-29-99 Антон.
Антон
Перезвоните мне пожалуйста по номеру 8(904) 332-62-08 Антон.
Антон
Перезвоните мне пожалуйста, 8 (904) 606-17-42 Антон.
Антон
Перезвоните мне пожалуйста по номеру. 8 (953) 367-35-45 Антон
Ксения
Текст от профессионального копирайтера. Готово через 1 день. Консультация бесплатно. Жми roholeva(точка)com