Консольные приложения
Каждое
приложение VB .NET должно иметь точку
вто§а. В точке входа содержится
код, автоматически выполняемый при
запуске, после чего управление
передается остальному коду
программы. В относительно простых
графических приложениях точка входа может ассоциироваться с начальной формой, как в VB6. Но как было показано в главе 1, код форм Windows достаточно сложен и поиск точки входа может вызвать определенные затруднения. В этой главе рассматриваются только консольные приложения, работающие в консольном окне (наподобие окна сеанса DOS). Да, VB .NET позволяет легко создавать традиционные консольные приложения, часто применяемые при программировании серверных сценариев:
Точкой входа
консольного приложения является
процедура Sub Mai n модуля (аналог
процедуры Sub Mai n в VB6). Если выбрать в
диалоговом окне New Project значок
консольного приложения (Console Application),
VB .NET автоматически генерирует «скелет»
приложения с точкой входа —
процедурой Sub Main:
Module Module1
Sub Main()
End Sub
End Module
В отличие от VB6,
в первой строке задается имя модуля
(команда выделена жирным шрифтом). В
данном примере используется имя Modul
el, принятое по умолчанию. По
правилам имя модуля должно
совпадать с именем файла. Допустим,
вы изменили имя модуля в первой
строке: Module Testl При попытке
запустить консольное приложения
выводится сообщение об ошибке:
Startup code 'Sub Main' was specified in 'Test.Modulel'.
but 'Test.Modulel'
was not found
Переименование
модуля после его создания
выполняется следующим образом:
- Измените
имя модуля в окне программы.
- Измените
имя файла модуля в окне решения.
- Щелкните
правой кнопкой мыши в строке
ConsoleApplication окна решения и
выберите в контекстном меню
команду Properties.
- Убедитесь
в том, что в списке Startup object
появившегося диалогового окна
(рис. 3.1) выбрано имя модуля.
По аналогии с VB6
программа VB .NET (решение) может
состоять из нескольких модулей, но
наличие процедуры Sub Main допускается
только в одном модуле. Приложение
завершается по достижении команды
End Sub процедуры Sub Mai n. Например,
легендарная программа «Hello world»
выглядит следующим образом:
Module Modul el
Sub Main()
Console.WriteLine("Hello
world")
End Sub End Module
Если запустить
эту программу в IDE, на экране очень
быстро мелькнет (и тут же исчезнет)
окно DOS со словами «Hello world». Окно
закрывается по завершении
обработки команды End Sub.
Рис. 3.1. Диалоговое
окно свойств консольного
приложения
Если включить в
программу строку, выделенную ниже
жирным шрифтом, консольное окно
остается на экране до нажатия
клавиши Enter (чрезвычайно полезный
метод ReadLine() описан ниже).
Module Modulel
Sub Main()
Console.WriteLine("Hello world")
Console. ReadLine()
End Sub
End Module
Несмотря на простоту, эти две программы демонстрируют одну из ключевых особенностей программирования VB .NET (и вообще программирования на любом объектно-ориентированном языке): вы обращаетесь к объектам с запросом на выполнение операций. По аналогии с VB6 точка («.») используется для обращения к членам объектов и классов. Хотя обычно при вызове указывается объект (конкретный экземпляр, созданный на базе класса), в некоторых случаях вместо него указывается имя класса. В качестве примера возьмем следующую строку:
Console.WriteLine("Hellо
world")
В ней
вызывается метод Wri teLi ne класса Console,
предназначенный для вывода текста
с последующим переводом строки (в
объектно-ориентированном
программировании, как и в VB6,
функции классов обычно называются методами).
Метод WriteLine принадлежит к числу общих
(shared) методов, также называемых
методами класса. Общие методы
подробно описаны в главе4. При
вызове WriteLine выводимый текст
заключаете в кавычки и помещается в
круглые скобки. Во вторую версию
программы «Hello world» добавлен вызов
метода ReadLi ne, ожидающего нажатия
клавиши Enter (метод ReadLi ne обычно
используется в правой части
команды присваивания, чтобы
введенный с консоли текст был
сохранен в заданной переменной —
см. следующее примечание).
Пользователям
предыдущих версий VB следует учесть,
что круглые скобки при вызове
методов обязательны — обычно IDE
добавляет их автоматически, но
лучше не забывать об этом. Ключевое
слово Call разрешено, но теперь в нем
нет необходимости.
При вводе
программ VB .NET во внешнем редакторе
вы не сможете воспользоваться
средствами IntelliSense. Мы рекомендуем
использовать IDE, поскольку
технология IntelliSense значительно
упрощает программирование в такой
сложной среде, как .NET (конечно, для
этого вам придется перейти от
бесплатно распространяемого .NET SDK к
Visual Studio). Редактор IDE даже
исправляет некоторые
распространенные ошибки —
например, пропуск круглых скобок
при вызове некоторых методов.
Тем не менее VS .NET
IDE пытается оформлять программы VB .NET
по своим правилам. Первые символы
ключевых слов преобразуются к
верхнему регистру, а строки
дополняются пробелами для удобства
чтения (End SUB преобразуется в End Sub и т.
д.). Регистр символов в именах
методов VB .NET определяется по схеме
Pascal (слова начинаются с прописных
букв, остальные буквы строчные).
Альтернативная схема выбора
регистра (writeLine) для методов VB .NET
обычно не используется.
Номера строк в
командах VB .NET практически не
используются, хотя строки
программы могут нумероваться,
причем каждая команда обычно
расположена в отдельной строке.
Чтобы продолжить команду в
следующей строке, завершите ее
символом подчеркивания (_),
отделенным одним или несколькими
пробелами. Таким образом, если
строка не завершается символом
подчеркивания, нажатие клавиши Enter
является признаком конца команды (в
Visual Basic команды не разманд можно
разместить в одной строке, разделив
их символом «:», но обычно так не
поступают. Если введенная строка не
помещается в окне, IDE прокручивает
строку вправо по мере
необходимости.
Комментарии в VB
.NET, как и в любом языке
программирования, необязательны.
Они не обрабатываются компилятором
и соответственно не занимают места
в откомпилированном коде. В VB .NET
существует два варианта оформления
комментариев. В первом, более
распространенном варианте
комментарий начинается с апострофа:
Sub Main()
Console.WriteLine("Hello
world")
'
Игнорировать значение,
возвращаемое методом ReadLine
Console. ReadLine()
End Sub
Во втором
варианте используется старое
ключевое слово Rem, которое
появилось в BASIC в начале 1960-х годов!
При включении
комментариев в конец строки проще
воспользоваться апострофом,
поскольку ключевое слово Rem
придется отделять двоеточием. В VB .NET
не предусмотрено языковых средств
для комментирования нескольких
строк, хотя на панели инструментов
присутствует кнопка, упрощающая
создание таких комментариев.
Ускоренная проверка
Если компилятор обнаруживает, что проверенная часть сложного логического условия однозначно определяет результат, он не проверяет остаток выражения. Это называется ускоренной проверкой (short curcuiting). Например, если в следующем примере переменная foo ложна, компилятор не проверяет переменную bar:
If foo And bar Then...
Так было в VB .NET
бета-версии 1, но в прежних версиях VB
ускоренная проверка не применялась.
После многочисленных жалоб
разработчики Microsoft вернули старую
интерпретацию логических
операторов And и Or и добавили новые
ключевые слова AndAlso и OrElse,
поддерживающие ускоренную
проверку:
If foo AndAlso Then...
В качестве
альтернативы для громоздких
конструкций с множеством Elself в VB .NET
была сохранена команда Select Case,
упрощающая принятие решений в
зависимости от состояния числовой
или строковой переменной. Пример:
Select Case average
Case Is > 90
Console.WriteLine("A")
Case Is > 80
Console. Wri teLi ne("B")
Case Is > 70
Console.WriteLine("C")
Case Else
Console.WriteLine("You fail")
End Select
Программисты с
опытом работы на С и Java, обратите
внимание — команда break не нужна,
поскольку выполняется только одна
секция Case. Дискретные наборы
значений перечисляются через
запятую, а ключевое слово То
позволяет задавать интервалы:
Select Case yourChoice
Case 1 To 9
' Порядок
Case -1. 0
' Неправильный ввод
End Select
Говоря об
управляющих конструкциях, нельзя
обойти вниманием команду GoTo. Если
перефразировать старую шутку,
современные программисты делятся
на три группы: те, кто не знает, как
пользоваться GoTo, и знать не хочет;
те, кто не знает, но переживает по
этому поводу; и те, кто умеет ею
пользоваться.
Частое
использование GoTo приводит к
многократным передачам управления
и порождает «спагетти-код», который
трудно читать и отлаживать. С
другой стороны, в некоторые
ситуациях применение GoTo делает
программу более понятной и
логичной — например, если в какой-то
ситуации потребовалось выйти сразу
из нескольких вложенных циклов.
Команда Exit для этого не подходит,
поскольку она завершает только
текущий цикл.
Чтобы
воспользоваться командой GoTo в VB .NET,
необходимо присвоить метку
соответствующей строке. Метка
начинается в первой позиции строки,
ее первым символом является буква,
а последним — двоеточие.
Старайтесь присваивать меткам
содержательные имена. Пример:
Bad-Input:
' Фрагмент,
выполняемый при переходе
Предположим, в
нашей программе данные вводятся во
вложенном цикле For. Чтобы завершить
ввод, пользователь вводит ZZZ :
SubMain()
Dim getData As String
Dim i, j As Integer
For i = 1 To 10
For j = 1 To 100
Console.Write("Type
the data, hit the Enter key between " & _
"ZZZ to end: ") getData = Console. ReadLine()
If getData = "ZZZ"
Then
Goto Bad Input Else
' Обработка данных
End If
Next j
Next i
Exit Sub
BadInput:
Console.WriteLine("Data entry ended at user request")
Console. ReadLine()
End Sub
Выходить из
вложенного цикла командой Exit For
неудобно — нам пришлось бы писать
дополнительный код для выхода из
внешнего цикла. Обратите внимание:
команда Exi t Sub предотвращает
передачу управления помеченному
коду после завершения обоих циклов.
Начиная с бета-версии
2 логические операторы (Not, And, Or и т. д.)
работают на уровне двоичных
разрядов, как и в прежних версиях VB.
Допустим, у вас имеются два целых
числа X и Y. Каждый бит результата X And
Y равен 1 лишь в том случае, если
равны 1 соответствующие биты обоих
операндов; в противном случае бит
результата равен нулю. Таким
образом, при вычислении результата
X And Y вычисляется каждый бит 32-разрядного
целого числа. Пример:
X = 7 'В двоичном представлении = 0111
Y = 12 'В
двоичном представлении = 1100
Выражение X And Y в
двоичной системе равно 0100 (4 в
десятичной системе), поскольку лишь
во второй позиции оба бита равны 1.
Остальные биты результата равны 0,
поскольку в этих позициях хотя бы
один из битов операндов равен 0.
Этот способ позволяет проверить
значения отдельных битов целого
числа. Примеры:
(X And 1) = 1:
проверить, установлен ли младший
бит числа.
(X And 2) о 2:
проверить, установлен ли
предпоследний бит числа (поскольку
в
двоичной
системе число 2 представляется
записью 10).
X And 255:
младший байт числа (255 дес. = 11111111 дв.).
X And 65280:
старший байт числа (65280 дес. =
1111111100000000 дв.).
Значение,
предназначенное для проверки
отдельных битов числа, называется маской
(mask).
В VB .NET имена
массивов должны подчиняться тем же
правилам, что и имена переменных.
Ссылка на элемент массива выглядит
как имя массива, за которым в
круглых скобках указывается индекс.
Массивы VB .NET во
многом отличаются от массивов VB6.
Одни изменения видны сразу, другие
не столь очевидны. Наиболее
заметные изменения перечислены
ниже.
- Индексация-элементов
в массивах начинается с 0. На
момент написания книги
ключевое слово То не
поддерживалось — будем
надеяться, что оно еще вернется!
Начиная с бета-версии 2 объявление 01m stri ngLi st(7) создает массив из восьми элементов с индексами от 0 до 7. Поскольку в VB .NET индексация всегда начинается с нуля, третий элемент массива обозначается stri ngList(2), а предшествующие элементы обозначаются stringList(0) и stringList(l).
- Все
массивы VB .NET являются
динамическими. Во время работы
программы их можно
переобъявить с новым размером
при помощи команд ReDim (с потерей
текущего содержимого) и ReDim
Preserve (с сохранением текущего
содержимого). Пример:
Dim x() As Single
ReDim x(20) ' Начиная с бета-версии 2. создает массив из 21 элемента
ReDim Preserve x(50) ' 21 элемент сохраняется в массиве.
- Массивы
могут инициализироваться при
объявлении, как показывает
следующий пример:
Dim weekend() As
String = {Saturday. Sunday}
Менее очевидные
изменения обусловлены тем, что
массивы VB .NET являются экземплярами
класса Array. Подробности будут
рассмотрены в главе 4, а пока
достаточно указать, что это
позволяет выполнять операции с
массивами вызовом методов класса
Array. Ниже продемонстрирован пример
сортировки массива методом Sort:
Sub Main()
Dim stuff() As
Integer = (9. 7, 5, 4, 2. 1, -37, 6}
Array.Sort(stuff)
Dim i As Integer
For i = 0 To UBound(stuff)
Console.WriteLine(stuff(i))
Next
Console. ReadLine()
End Sub
Программа
выводит массив, отсортированный с
применением чрезвычайно
эффективного алгоритма «быстрой
сортировки».
Массивы с индексацией элементов в заданном интервале
Утверждение о
том, что индексация массивов всегда
начинается с 0, не совсем точно.
Теоретически можно определять
массивы с заданной верхней и нижней
границей индекса, но из-за
неудобного синтаксиса и снижения
быстродействия вряд ли вам
захочется это делать. В следующем
фрагменте создается массив с
индексацией элементов от 1995 до 2002:
Sub Main()
Dim anArray As Array
Dim i As Integer
Dim i(0) As Integer
Dim lowerBounds(0)
As Integer
i(O) = 7
lowerBounds(0) =
1995 ' Создать массив с индексами 1995 -
2002
аnАrrау = Array.CreateInstance(GetType(System.Int32).
1. lowerBounds) anArray.SetValue(200000, 1995) anArray.SetValue(1000000.
2001)
Console.WriteLine("The entry in position 1995 is " & _ (anArray.GetValue(1995).ToString))
Console.WriteLine("The entry in position 2002 is " & _ (anArray.GetValue(2001).ToString))
Console. ReadLine()
End Sub
Присваивание
выполняется методом SetValue (значение,индекс),
а чтение — методом GetValue(индекс). Но
если массив создается подобным
образом в режиме жесткой проверки
типов, вам придется позаботиться о
том, чтобы присваиваемое значение
было преобразовано к правильному
типу!
Цикл For-Each
Содержимое
массива часто перебирается в цикле
от 0 до UBound(массив), однако вы также
можете воспользоваться
конструкцией For-Each. Синтаксис For-Each
выглядит следующим образом:
For Each
переменная In массив
[команды]
[Exit For при
необходимости]
[команды]
Next
Конструкция For-Each
универсальна и может
использоваться в тех случаях, когда
структура данных поддерживает
итеративный перебор элементов. За
подробностями обращайтесь к главе 4.
Массивы не
ограничиваются одним измерением.
Допустим, вы хотите сохранить
таблицу умножения в матричном виде.
Примерное решение может выглядеть
так:
Dim mulTable(11.11) As Integer
' Создает массив 12x12
Dim i As Integer, j As Integer
For i = 0 To 11
For j = 0 To 11
mulTable(i.j) = (i+l)*(j+l)
Next j
Next i
Размеры
массивов в VB .NET могут изменяться, но
количество измерений должно
оставаться постоянным.
Многомерный
массив с неопределенным
количеством элементов объявляется
при помощи запятых. Следующий
пример показывает, как объявить
трехмерный массив:
Dim salesByDivision(
, , ) As Decimal
Команда ReDim
задает или изменяет количество
элементов в каждом измерении, но
размерность массива не изменяется.
Раньше выбор
между процедурой (Sub) и функцией (Function)
определялся простым критерием:
если вы собирались использовать
возвращаемое значение, следовало
выбирать функцию, а если нет —
процедуру. Мы рекомендуем
придерживаться этой модели, хотя
ничто не мешает проигнорировать
возвращаемое значение функции. В
объектно-ориентированных
программах функции и процедуры
обычно включаются в классы и
называются методами.
В VB .NET, как и во
многих языках программирования,
существуют два способа передачи
параметров функциям и процедурам: передача
по ссылке и передача по
значению. Когда параметр
передается по ссылке, его изменения
внутри функции приведут к
изменению исходного аргумента
после выхода из функции. По
умолчанию в VB .NET параметры
передаются по значению (а в VB6 — по
ссылке).
Чтобы создать
новую функцию или процедуру в окне
программы, установите курсор за
пределами других процедур и
функций и начинайте вводить
заголовок процедуры или функции.
Как только вы нажмете клавишу Enter,
редактор IDE автоматически создаст
команду End правильного типа (End Functi on
или End Sub). Ниже приведен заголовок
функции, которая получает целый
параметр по значению и возвращает
логическую величину (True или False) в
зависимости от того, принадлежит ли
переданный параметр интервалу от 1
до 10: Function IsBetweenlAnd10(ByVal num As Integer) As
Boolean
Полный текст
модуля с функций Is Between lAnd 10
приведен ниже. Порядок следования
функций не важен — функция Sub Mai n
может находиться и после
определения функции, которая в ней
используется.
Module Modulel
Function
IsBetweenlAnd10 (ByVal num As Integer) As Boolean
If num >= 1 And num <=10 Then
Return True
Else
Return False
End If
End Function
Sub Main()
Console.
WriteLinedsBetweenlAnd100))
Console. ReadLine()
End Sub
End Module
В VB .NET при
вызове функции или процедуры
непустой список параметров всегда
заключается в круглые скобки, как в
строке с вызовом Console.WriteLine: IsBetweenlAnd100)
Обратите
внимание на ключевое слово Return. При
выполнении команды Return функция
завершается и возвращает значение,
указанное после Return (значение
должно быть определенным —
возвращение аналога voi d не
допускается). Также поддерживается
синтаксис с присваиванием имени
функции, использовавшийся в
прежних версиях VB:
Function IsBetweenlAnd10(ByVal num As Integer) As Boolean
If num >= 1 And
num <= 10 Then
IsBetweenlAnd10 =
True Else
IsBetweenlAnd10= False
End If
End Function
Использование
Return — дело вкуса. Команда Return
нагляднее и проще, но старый
синтаксис оставляет управление
внутри функции, а это иногда бывает
удобно.
Обобщенная
форма определения функции выглядит
следующим образом:
Function имя_функции
(аргумент1, аргумент2, ...) As тип
команды
Return выражение ' или имя_функции = выражение
End Function
где аргумент1 и
аргумент2 — переменные. Имена
функций подчиняются тем же
правилам, что и имена переменных.
При вызове функции VB .NET выполняет
команды, содержащиеся в
определении функции. Значение,
указанное после Return (или последнее
значение, присвоенное имени
функции), определяет результат
вызова.
Обычно
количество аргументов,
передаваемых при вызове функции,
должно совпадать с количеством
параметров в ее определении. Типы
аргументов должны быть совместимы
с типами соответствующих
параметров, при этом автоматически
выполняются только расширяющие
преобразования. Например,
следующий фрагмент допустим,
поскольку преобразование Short в Integer
не приводит к потере данных:
Dim bar As Short = 3
Console.WriteLinedsBetweenlAnd10(bar))
VB .NET позволяет
создавать функции с переменным
числом аргументов. Дополнительная
информация приведена далее в этой
главе.
Процедуры
В отличие от
функций, процедуры не возвращают
конкретных значений. Вызов
процедур осуществляется по имени.
Непустые списки аргументов всегда
заключаются в круглые скобки. В
приведенном ниже примере строка с
вызовом процедуры выделена жирным
шрифтом:
Option Strict On
Module Modulel
Sub
ShowBottlesOfBeer(ByVal nbot As Integer)
Console.WriteLine(nbot
& " bottles of beer on the wall")
Console.Writeline(nbot
& " bottles of beer.")
Console.WriteLine("if
one of those bottles hsould happen to fall")
Console.WriteLine(nbot -1&" bottles of beer on the wall")
End Sub
Sub Main()
Dim I As Integer
For I = 10 To 1 Step -1
ShowBottlesOfBeer(I)
Next
Console.WriteLine("All
beer gone...")
Console. ReadLine()
End Sub
End Module
При вызове
процедур указывать ключевое слово
Sub не обязательно. Строку с вызовом
процедуры из приведенного выше
примера можно было записать и в
таком виде:
Call
ShowBottlesOfBeer(I)
Заголовок
процедуры должен содержать
объявления всех параметров с
ключевыми словами ByVal или ByRef (по
умолчанию используется ByVal, то есть
передача по значению):
Sub имя_процедуры(В(ByVа1
аргумент1 As тип. ByVal аргумент2 As тип,
....)
команды
End Sub
При вызове
процедуры в форме имя_процедуры(аргумент1,
аргумент2, ...) или Call имя_процедуры(аргумент1.
аргумент2, ...) VB .NET создает копии данных-аргументов
и выполняет код, содержащийся в
теле процедуры (поскольку в отличие
от предыдущих версий по умолчанию
параметры передаются по значению).
Преждевременный выход из функций или процедур
В некоторых
ситуациях требуется покинуть
функцию до того, как будет
достигнута стандартная точка
выхода (например, если проверка
покажет, что исходные данные
неверны и дальнейшие вычисления
бессмысленны). Команда Return
немедленно передает управление
вызывающей стороне (если не
определена секция Finally — см. главу 7):
Function BallOut (X
As Double) As Double If X < 0 Then
Return 0'
Вернуть фиктивное значение Else
' Основные действия
End If
End Function
'Выход из процедур осуществляется командой
Exit Sub.
Передача массивов функциям и процедурам
В VB .NET, как и в
прежних версиях VB, существуют
удобные средства для работы с
одномерными и многомерными
массивами в процедурах и функциях.
Впрочем, существуют некоторые
нюансы, обусловленные передачей по
ссылке и по значению; мы рассмотрим
их в главе 4. Перебор содержимого
массива осуществляется
конструкцией For Each или (более
распространенный вариант)
стандартным циклом For с вычислением
верхней границы при помощи функции
UBound (). Ниже приведен пример функции
поиска максимального элемента в
массиве:
Function FindMax(ByVa1
a() As Integer
Dim finish As
Integer = UBound(a)
Dim max As Integer =
a(0)
Dim i As Integer
For i = 0 To finish
If a(i) > max
Then max = a(i)
Next i
Return max End
Function
Обобщенная
форма вызова UBound(имя_массива, I)
возвращает верхнюю границу по 1-му
измерению массива. Для одномерных
массивов (списков) параметр 1
является необязательным.
Процедуры и функции с необязательными аргументами
В VB. NET сохранена
возможность определения процедур и
функций с необязательными
аргументами, но в отличие от VB6 для
каждого необязательного параметра
должно быть указано значение по
умолчанию. Следующий пример
демонстрирует синтаксис
объявления необязательных
параметров:
Sub ProcessAddress(TheName
As String,
Address As String. City As String. State As String.
ZipCode As String.
Optional ZipPlus4 As String = "0000")
В данном
примере последний параметр
является необязательным (Optional) и по
умолчанию равен "0000".
VB .NET также
позволяет определять процедуры и
функции с произвольным количеством
аргументов. Для этого в качестве
параметра передается массив с
ключевым словом РаramАrrау, как в
следующем примере:
Function AddThemUp(ByVal
ParamArray stuff() As Double) As Double
Dim total As Double
= 0
Dim Number As Double
= 0
Dim I As Integer
For I = 0 To UBound(stuff)
total = total +
stuff(I)
Next
Return total End
Function
Пример
использования функции:
x = AddThemUp(3, 4.
5. 6)
В результате
переменной х присваивается
значение 18.
При вызове
функций и процедур с большим
количеством параметров (особенно
необязательных) существует такая
элегантная возможность, как
передача именованных аргументов. Если
значения параметров при вызове
передаются в виде «имя -:=значение»,
вам не придется беспокоиться о
соблюдении порядка аргументов (регистр
символов в именах игнорируется). В
отличие от прежних версий VB, где
именованные аргументы то работали,
то нет, в VB .NET они работают всегда.
Именованные
аргументы разделяются запятыми.
При разумном выборе имен
параметров именованные аргументы
заметно упрощают чтение программы,
особенно при большом количестве
необязательных аргументов. Для
примера возьмем приведенный выше
заголовок функции ProcessAddress:
Sub ProcessAddress(TheName
As String.
Address As String. City As String. State As String,
ZipCode As String,
Optional ZipPlus4 As String = "0000")
Вызов этой
процедуры может выглядеть так:
ProcessAddress(Address
:= "The Whitehouse"
Name := "GeorgeW",
City := "DC".
_
State:= String.Empty.
_
ZipCode:= "12345")
Обратите
внимание: порядок перечисления
аргументов отличается от заданного
в заголовке процедуры.
В VB .NET, как и в
любом сколько-нибудь серьезном
языке программирования,
поддерживается рекурсия — решение
задач посредством сведения их к
более простым задачам того же типа.
Одним из стандартных примеров
рекурсивного решения является
перебор дерева каталогов на диске (см.
главу 9).
На
концептуальном уровне рекурсивное
решение выглядит следующим образом:
Решение
задачи с применением рекурсии
If задача
тривиальна
Решить Else
Упростить
задачу, сводя ее к однотипной, но
более простой задаче
Решить более простую задачу с применением рекурсии
End If
(Возможно)
Объединить решение простой задачи (или
задач)
с решением
исходной задачи.
Рекурсивная
функция или процедура постоянно
вызывает сама себя, непрерывно
упрощая задачу до тех пор, пока ее
решение не станет тривиальным; в
этот момент задача решается, и
происходит возврат к предыдущему
уровню. Применение рекурсии
нередко связано с принципиальным
изменением подхода к некоторым
задачам, порождающим особенно
элегантные решения и столь же
элегантные программы (кстати,
многие алгоритмы сортировки —
такие, как встроенный метод Sort
класса .NET Array, — основаны на
принципе рекурсии).
В качестве
примера мы рассмотрим программу
поиска наибольшего общего делителя
двух целых чисел (то есть
наибольшего целого числа, на
которое они оба делятся без остатка).
Пример:
- НОД(4,6) = 2 (наибольшее число, на которое 4 и 6 делятся без остатка).
- НОД(12,7)
- 1 (числа 12 и 7 не делятся ни на
одно целое число, большее 1).
Около 2000 лет назад Евклид предложил следующий алгоритм вычисления НОД двух целых чисел а и b:
- Если
а делится на b, НОД= b. В
противном случае НОД (а, b) = НОД (b,
a Mod b)
Вспомним, что
функция Mod возвращает остаток от
целочисленного деления, а
выражение a Mod b,равно 0 лишь в том
случае, если а кратно b. Пример:
НОД(126.12)=НОД
(12. 126 Mod 12)=НОД (12,6) - 6
Ниже приведен
пример рекурсивной функции для
вычисления НОД. В строке,
выделенной жирным шрифтом, функция
GCD вызывает сама себя для более
простого случая:
Option Strict On
Module Modulel
Function GCD(ByVal p As Long, ByVal q As Long) As Long
If Q Mod P = 0 Then
Return P Else
Return GCD(Q, P Mod Q)
End If
End Function Public
Sub Main()
Console.WriteLine("The GCD of 36 and 99 is " & GCD(36. 99))
Console. ReadLine()
End Sub
End Module
Сначала
обрабатывается тривиальный случай Q Mod P = 0. Если это
условие не выполняется, функция GCD
снова вызывает себя для более
простого случая, поскольку в
результате применения Mod мы
переходим к меньшим числам. В
приведенном примере объединять
результаты не нужно (как, например,
в функции сортировки).