| « Поставить закладку » « Сделать стартовой » | |||
|
|||
|
Статьи:: Программирование на Visual Basic 7 .NET) :: Глава 3. Выражения, операторы и передача управления
Глава 3. Выражения, операторы и передача управления
Глава №3. Выражения, операторы и передача управления В этой главе
представлен базовый «арсенал» VB .NET. Большая часть материала сводится к
краткому обзору концепций, присущих всем языкам программирования (например,
переменных и команд цикла), и описанию базовых типов данных, в основном
различных чисел и строк. Читатели, хорошо знакомые с VB6, могут бегло пролистать
эту главу. Лишь в
нескольких примерах этой главы встречается реальный код, который может
использоваться в серьезных программах VB .NET. Дело в том, что ни одна серьезная
программа VB .NET не обходится без объектов, построенных по шаблонам, называемых
классами, а эта тема будет рассматриваться в главе 4. Мы начнем с базовых
конструкций языка, потому что в противном случае нам пришлось бы ограничиться
примитивными классами, не обладающими никакой практической ценностью. В этой
главе не рассматриваются классы, определяемые пользователем, и
продемонстрированы лишь простейшие примеры использования встроенных классов .NET
Framework, обладающих исключительно широкими возможностями. Что же из этого
следует? Как ни странно — то, что написанные в этой главе программы весьма
близки по стилю к традиционному программированию ранней эпохи BASIC и даже
предшествовавшей ей эпохи Fortran и COBOL (если не считать некоторых странных,
но необходимых синтаксических конструкций). В частности, в отличие от программ
из дальнейших глав, у них всегда есть четко определенные начало и конец, и
управление передается от начала к концу (хотя управление может передаваться
специальными командами). Как говорилось
во введении, мы постараемся приводить программы, написанные в нормальном стиле
.NET, по возможности избегая искусственной совместимости с VB6. Каждое
приложение 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 Переименование
модуля после его создания выполняется следующим образом:
По аналогии с
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 не предусмотрено языковых
средств для комментирования нескольких строк, хотя на панели инструментов
присутствует кнопка, упрощающая создание таких комментариев.
Имена переменных в VB .NET имеют длину до 255 символов и обычно начинаются с буквы в кодировке Unicode (за дополнительной информацией о Unicode обращайтесь на сайт www.unicode.org), хотя также допускается символ подчеркивания. Далее следует произвольная комбинация букв, цифр и символов подчеркивания. Все символы имени являются значимыми, но регистр символов игнорируется (как вообще в VB .NET); считается, что firstBase и firstbase — одна и та же переменная. Присваивание выполняется при помощи знака =, как и в более ранних версиях VB: theYear = 2001
Имена переменных не могут совпадать с последовательностями, зарезервированными VB .NET (список для текущей версии приведен в табл. 3.1), однако это ограничение можно обойти, заключив имя переменной в квадратные скобки. Например, переменная не может называться Loop, а имя [Loop] подойдет — хотя делать это не рекомендуется. Зарезервированные слова внутри имен переменных допустимы (скажем, loopit — вполне нормальное имя). При попытке использования ключевого слова в качестве имени переменной VB .NET подчеркивает его и информирует об ошибке (при помощи экранной подсказки). Таблица
3.1. Ключевые слова текущей версии VB .NET
Литералы и их соответствие типам
данных Литералом
называется последовательность символов, которая может интерпретироваться как
значение одного из примитивных типов. Но с типами (даже примитивными) в VB .NET
дело обстоит несколько сложнее, чем в более ранних версиях VB. Хотя возможность
непосредственной интерпретации данных предусмотрена в любом языке
программирования, решить, как именно следует интерпретировать те или иные
данные, иногда бывает непросто. Наверное, все согласятся с тем, что 3 — это
число 3 и его следует интерпретировать именно так. Но что такое число 3 с точки
зрения компилятора? Сколько байт памяти следует под него выделить? Теоретически
для хранения числа 3 хватит 2 бит, но в современных языках программирования
обычно происходит не так. Итак, компилятор
должен проанализировать литерал и принять необходимые решения, поэтому вы должны
по возможности точнее описать, что вы имеете в виду, не полагаясь на разумность
компилятора. Вернемся к примеру с простым числом 3. В VB .NET оно может
представлять собой (среди прочего):
К счастью,
символ 3 никогда не будет автоматически интерпретироваться как строковая
константа (если не переопределять стандартную логику VB). В VB .NET строки и
числа по умолчанию не смешиваются — более подробно эта тема рассматривается в
разделе «Преобразования разнотипных значений» этой главы. С точки зрения
компилятора простой констатации «это число 3» недостаточно. Разумеется, VB .NET,
как и любой язык программирования, позволяет уточнить смысл литерала. Например,
31 — литерал типа Integer со значением 3, а литерал "3" относится к строковому
типу String (тип String рассматривается ниже в этой главе; он несколько
отличается от строкового типа в прежних версиях VB).
В переменной,
объявленной с примитивным типом, хранятся значения указанного типа. Ниже
перечислены примитивные числовые типы VB .NET.
Любой
целочисленный литерал можно записать в шестнадцатеричной системе счисления (по
основанию 16), для чего он снабжается префиксом &Н. Например, литерал
&HF соответствует десятичному числу 15, хранящемуся в формате Integer,
поскольку суффикс типа не указан, а число входит в интервал допустимых значений
типа Integer. Числа, записанные в восьмеричной системе счисления (по основанию
8), снабжаются префиксом &0. При выполнении
операций с вещественными числами используются следующие типы:
Новый тип
Decimal пришел на смену старому типу Currency, использовавшемуся в прежних
версиях VB. Он используется в ситуациях, когда ошибки округления
недопустимы.
Применение
суффикса типа в литералах помогает избежать путаницы и случайных ошибок
переполнения, возникающих при умножении двух чисел. При выполнении следующей
команды: Console.WriteLine(12345678 * 4567) компилятор
выдает ошибку: This constant expression produces a value that is not representable in type System.Integer. Проблема решается при помощи суффикса типа Long: Console.WriteLine(123456781 * 4567) Общие методы
MaxValue и MinValue, ассоциированные с типом, возвращают соответственно верхнюю
и нижнюю границы интервала допустимых значений. Пример: Console.WriteLine(Integer.MaxValue) В табл. 3.2
собраны данные о соответствии числовых типов VB .NET, типов .NET Framework и их
аналогов из VB6 (если они есть). Таблица
3.2. Соответствие между числовыми типами
Кроме числовых
литералов также существуют литералы типов Boolean, Date и Char. Тип данных Bool
ean принимает значения True и Fal se. В VB .NET он представляется 4 байтами (в
отличие от 2 байт в VB6).
Тип данных Date
представляет дату и/или время. Как ИГ в VB5, такие литералы заключаются между
символами #...# — например, #Jan 1. 2001#. Если время не указано),
предполагается, что литерал соответствует полуночи указанной
даты.
Тип данных Char
представляет один символ Unicode. Объем кодировки Unicode (65 536 символов)
вполне достаточен для представления всех существующих алфавитов. Обычно символ
заключается в кавычки, за которыми следует префикс С (например, "Н"С), но вы
также можете воспользоваться встроенной функцией Chr и указать числовой код
символа Unicode. Например, запись Chr(&H2153) представляет символ 1/3
кодировке Unicode, хотя в некоторых операционных системах этот символ не будет
отображаться во время работы программы. Если заключить один символ в кавычки без
суффикса «С», вы получите тип Stri ng вместо Char, а автоматическое
преобразование между этими типами не поддерживается (команда Opti on Strict
описана ниже в этой главе). В VB .NET, как и
в VB6, переменные объявляются в процедурах и функциях при помощи ключевых слов
Dim и As, а присваивание выполняется знаком =: Dim foo As String foo =
"bar" Если вы не
изменяли стандартную настройку VB .NET, переменные должны объявляться перед
использованием (режим Option Explicit, впервые представленный в VB4, теперь
используется по умолчанию). В VB .NET поддерживается инициализация переменных
при объявлении. Пример: Dim salesTax As
Decimal = 0.0825D Команда
объявляет переменную с именем salesTax и присваивает ей начальное значение
0.0825 типа Decimal. При инициализации могут использоваться любые синтаксически
правильные выражения VB .NET. Следующая команда присваивает переменной
startAngle встроенное значение математической константы п, используя для
этого константу класса System. Math: Dim startAngle As Decimal -
Math.PI Если переменная
не была инициализирована при объявлении, ей присваивается стандартное значение,
соответствующее ее типу, — например, числовым переменным присваивается 0. При
таком удобном синтаксисе, как в VB .NET, всегда лучше инициализировать
переменную при объявлении, чем полагаться на значение по умолчанию. В следующем
фрагменте используется оператор &, применявшийся в VB6 для конкатенации
строк: Sub
Main() Dim salesTax As
Decimal = 0.0825D Dim state As String
= "California" Console.WriteLine("The sales tax in " & state & " is " &
salesTax) Console. ReadLine() End
Sub Программа
выводит следующий результат: The sales tax in
California is 0.0825 В отличие от предыдущих версий VB, объявление нескольких переменных в одной строке программы работает именно так, как подсказывает здравый смысл. Иначе говоря, следующая команда объявляет три переменные: i, j и k, относящиеся к типу Integer: Dim i, j, k As
Integer При
одновременном объявлении нескольких переменных инициализация выполняться не
может, поэтому следующая строка недопустима: Dim i, j, k As
Integer = 1 Как и в прежних
версиях VB, вместо указания типа с ключевым словом As может использоваться
суффикс типа. Например: Dim i%,
myname$ Приведенная
команда объявляет переменную i типа Integer (аналог Long в старом VB) и
переменную myName типа String. Программистам VB .NET поступать подобным образом
не рекомендуется. Все программисты
хорошо помнят, какие жаркие дискуссии проходили по поводу соглашений об именах
переменных. Существует сложная система префиксов (так называемая венгерская
запись), позволяющая с первого взгляда определить тип переменных. Согласно общим
рекомендациям программирования для .NET Framework применение венгерской записи
нежелательно. Мы будем следовать этим рекомендациям, и в книге префиксы
встречаются очень редко.
Преобразования разнотипных значений По мнению многих
программистов, прежние версии VB6 слишком либерально относились к преобразованию
типов. В результате возникало явление «злостного искажения типов» — скажем, VB6
позволял умножить строковое представление числа на Integer. В VB .NET
предусмотрен режим жесткой проверки типов Option Strict. Чтобы активизировать
его, включите следующую команду в начало программы (также можно воспользоваться
флажком Strict Type Checking на вкладке Build диалогового окна Project
Properties): Option Strict
On При активизации
этого режима (а это следует делать всегда!) VB .NET требует, чтобы любые
преобразования типов, которые могут привести к потере данных, выполнялись явно.
Например, при преобразовании Single к типу Integer может произойти потеря
точности, поскольку тип Integer не позволяет представить весь интервал
допустимых значений типа Single. С другой стороны, если потеря данных исключена
(скажем, при преобразовании Integer в тип Long или Decimal), VB .NET выполняет
преобразование автоматически. В документации VB .NET преобразования без потери данных
называются расширяющими преобразованиями (widening conversions). В табл.
3.3 переделены допустимые расширяющие преобразования для базовых типов
данных. Таблица
3.3. Допустимые расширяющие преобразования для базовых типов VB
.NET
Более того, при
активном режиме жесткой проверки типов вы не сможете использовать
конструкции вида: Dim foo As Boolean foo = 3 В этом фрагменте
логической переменной foo значение True присваивается в виде ненулевого числа (в
VB6 это было вполне распространенным явлением). Подобные преобразования
должны выполняться явно: Dim foo As Boolean foo
=СВооl(З) VB .NET
автоматически выполняет преобразование между символьным типом и строкой,
состоящей из одного символа. При желании вы
можете вернуться к доисторическим временам и отказаться от жесткой проверки
типов. Для этого достаточно начать модуль со следующей команды: Option Strict Off Впрочем,
поступать подобным образом не рекомендуется. Если содержимое
переменной одного типа может быть преобразовано к другому типу, можно
воспользоваться функцией явного преобразования, как в только что приведенном
примере с СВооl. Функции явного преобразования типов перечислены в табл.
3.4. Таблица
3.4. Функции явного преобразования типов
,VB .NET
выполняет числовые преобразования только в том случае, если преобразуемое число
входит в интервал допустимых значений нового типа; в противном случае выдается
сообщение об ошибке.
Вероятно, вы
заметили, что при описании типов нигде не упоминается тип Variant. BVB .NET этот
тип не поддерживается — и это очень хорошо! В VB6 переменные Variant допускали
хранение данных произвольного типа. Программисты часто злоупотребляли этой
возможностью, что приводило к возникновению нетривиальных ошибок в программах. В
VB .NET все типы данных (даже числовые, как Integer) являются частными случаями
типа Object. Может показаться, что тип Object стал аналогом Variant в VB .NET,
но это не так. Как будет показано в главах 4 и 5, тип Object занимает в
программировании .NET значительно более важное место и обладает множеством
интересных возможностей. Мы вернемся к типу Object в главах 4 и
5. Ниже приведен
хрестоматийный пример — преобразование температуры по Цельсию в температуру по
шкале Фаренгейта. Мы руководствуемся следующими предположениями:
' Преобразование температуры по Цельсию в температуру по Фаренгейту Option Strict On Module Modulel Sub
Main() Dim cdeg As
Decimal Console. Writer
Enter the degrees in centigrade...") cdeg =
CDec(Console.ReadLine()) Dim fdeg As
Decimal fdeg = (((9@ / 5) *
cdeg) + 32) Console.WriteLine(cdeg & " is " & fdeg & " degrees
Fahrenheit.") Console.
ReadLine() End Sub End
Module Обратите
внимание на суффикс @ — он гарантирует, что при вычислениях будет использоваться
тип Decimal. Если убрать этот суффикс, то при включенной жесткой проверке типов
будет выдано сообщение об ошибке! При
использовании простого оператора / для деления в VB .NET необходимо учитывать
некоторые нюансы. За дополнительной информацией обращайтесь к разделу
«Математические операторы». Строковая
переменная содержит текст в кодировке Unicode длиной до 231 (более 2
миллиардов!) символов. Как было показано выше, значения строкового типа
заключаются в кавычки: Dim message As String message =
"Help" Конкатенация
(объединение) строк обычно выполняется оператором &. Старый вариант с
оператором + тоже работает, но при отключении жесткой проверки типов он может
вызвать серьезные проблемы, поэтому использовать знак + при конкатенации не
рекомендуется. Старый способ идентификации строковых переменных с суффиксом $
(например, aStringVariableS) иногда используется для временных
переменных.
В вашем
распоряжении остались все классические строковые функции VB6 (Left, Right, Mid и
т. д.), но версии этих функций с суффиксом $ теперь не поддерживаются. В табл.
3.5 перечислены важнейшие функции класса String, заменяющие строковые функции
VB6. Не забывайте, что при многократной модификации строк (например, при вызове
Mid в цикле) следует использовать класс StringBuilder, описанный в главе 4.
Некоторые из приведенных методов используют массивы, которые будут рассмотрены
ниже в этой главе. При
программировании для .NET рекомендуется по возможности использовать методы и
свойства класса Stri ng, входящего в .NET Framework. Самые распространенные
строковые методы перечислены в табл. 3.6. Таблица
3.5. Основные строковые функции
|