Hello, C#
ГЛАВА 3
Hello, C#
Прежде чем приняться за главное в нашей теме — части II "Основы классов С#" и III "Написание программ", я предлагаю вам поучаствовать в разработке небольшого С#-приложения. В начале этой главы вы узнаете о достоинствах и недостатках редакторов, в которых можно писать программы на С#. Выбрав подходящий редактор, мы создадим каноническое приложение "Hello, World" и попутно познакомимся с основным синтаксисом и схемой создания С#-приложений. Вы увидите, что синтаксис С#, как и большинства других языков, довольно шаблонен, и вы можете использовать приложение из этой главы как трафарет при написании собственных Сопрограмм. Затем вы научитесь компилировать код из командной строки, а затем и запускать свое приложение.
Давайте пройдем шаг за шагом все этапы подготовки и запуска С#-приложения.
Прежде чем начать писать приложение, надо выбрать редактор. В этом разделе я кратко расскажу о наиболее популярных редакторах и посоветую выбрать подходящий.
Notepad
Среди разработчиков первых приложений на С#, применявших .NET Framework SDK, самым популярным редактором был Microsoft Notepad. Когда я писал эту книгу, у меня были несколько иные причины пользоваться им, о которых скажу ниже. Однако вам я не советую Notepad, a почему — вы сейчас поймете.
- Исходные файлы на С# должны иметь расширение .cs, и при сохранении файла у вас будут проблемы. Дело в том, что если в диалоговом окне Save As ввести имя файла с расширением, скажем, Test.cs, то файл запишется с именем test.cs.txt. Чтобы этого не происходило, нужно каждый раз в списке Туре устанавливать строку All Files.
- В Notepad не показываются номера строк — это очень затрудняет поиск ошибки, о которой компилятор сообщает, указывая номер ошибочной строки.
- Табуляторы в Notepad имеют фиксированную длину в восемь позиций, поэтому приложения посложнее "Hello, World" читаются с трудом.
- Notepad не выполняет автоматического отступа на следующей строке после нажатия Enter. Поэтому придется вручную сдвигать текст на требуемое число позиций. Кажется, этих причин достаточно, чтобы отказаться от Notepad.
Visual Studio 6
В прошлом я разрабатывал приложения для Microsoft Windows на языке Microsoft Visual C++, так что выбор Microsoft Visual Studio 6 был для меня вполне естественен. Visual Studio — полноценный редактор, имеющий все средства для редактирования и сохранения С#-файлов.
Для программиста очень важно, если в редакторе имеется подсветка синтаксиса. Увы, Visual Studio старше С# на несколько лет, и чтобы приспособить подсветку синтаксиса для С#, в редакторе нужно кое-что "подкрутить". Сначала требуется внести изменения в реестр Windows. С помощью редактора реестра, скажем, Regedit.exe, найдите в нем параметр HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Text Editor\Tabs/Language Settings\C/C++\FileExtensions. В нем вы увидите строку:
cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2
Добавьте в ее конец расширение cs. (Ставить в конце точку с запятой не обязательно.) Новый параметр регистра будет выглядеть так:
cpp;cxx;c;h;hxx;hpp;inl;tlh;tli;rc;rc2;cs
Теперь при открытии файла с расширением .cs Visual Studio будет поддерживать этот тип файла.
Затем нужно сообщить Visual Studio, какие слова являются ключевыми в С#. Для этого создайте и поместите в одну папку с файлом msdev.exe текстовый ASCII-файл usertype.dat. В нем нужно перечислить ключевые слова, которые будут подсвечиваться, — по слову в каждой строке файла. Visual Studio прочитает этот файл при запуске — чтобы увидеть, как отразились на редакторе внесенные вами изменения, закройте Visual
Studio, если он был открыт, и запустите его заново. Файл usertype.dat с перечислением всех ключевых слов С# см. на прилагаемом к книге компакт-диске. Вот как будет выглядеть ваш С#-код после описанных действий (рис. 3-1):
Рис. 3.1. Подсветка синтаксиса в Visual Studio 6 позволяет воочию убедиться в правильности набора ключевого слова.
Visual Studio.NET
Спору нет, только Visual Studio.NET может обеспечить полноценную работу в среде .NET. Помимо интегрированных в среду разработки инструментов и мастеров для создания С#-приложений, вы найдете там средства, повышающие производительность, вроде IntelliSense и Dynamic Help. IntelliSense автоматически отображает при вводе состав класса или пространства имен, избавляя вас от необходимости держать в памяти все члены каждого класса. IntelliSense показывает также все аргументы и их типы, когда сразу после имени метода вы вводите открывающую скобку. В Visual Studio 6 такое средство тоже есть, но в нем не поддерживаются типы и классы С#. Dynamic Help — новинка для Visual Studio. При наборе в редакторе своего кода вы увидите в отдельном окошке информацию о слове, вводимом в данный момент. Если, например, это ключевое слово namespace, в окне видны гиперссылки на разделы справочной системы, относящиеся к ключевому слову namespace.
Прочие редакторы
Не будем забывать, что есть и другие популярные редакторы, такие как CodeWright фирмы Starbase или Visual SlickEdit от MicroEdge. He вдаваясь в подробности, отмечу лишь, что для написания С#-приложения вы можете использовать любой из них.
Чем я пользовался в этой книге
Я начал работу над этой книгой, когда еще шло тестирование Visual Studio.NET, поэтому мне пришлось использовать Visual Studio 6. Надеюсь, работа в среде, не предназначенной для С#, помогла мне сделать книгу полезной для всех, кто намерен создавать приложения на С# независимо от выбранной ими среды разработки. Как я уже отмечал, при работе с примерами из этой книги вы можете применять Notepad, и на их результатах это не отразится.
Итак, вы выбрали среду разработки и готовы приступить к своему первому приложению на С#, в качестве которого традиционно выступает приложение "Hello, World". Введите данный код в файл и сохраните его под именем Hello World, cs:
class HelloWorld
{
public static void Main()
{
System.Console.Writel_ine("Hello, World");
}
He пугайтесь, если что-то в этом коде кажется вам непонятным. Знакомясь с первым приложением, мы пока ограничимся компиляцией кода и запуском. Убедившись, что наша среда разработки позволяет правильно компилировать и запускать С#-приложения, мы перейдем к подробному разбору самого кода.
Если в ваш редактор встроено средство сборки С#-приложений, этот этап может вызвать у вас затруднения. Чтобы не отвлекаться на описание возможностей разных редакторов, я буду на протяжении всей книги запускать компилятор (csc.exe) только из командной строки. В этом два плюса. Во-первых, все этапы построения демонстрационных примеров будут пройдены независимо от того, какой средой разработки вы пользуетесь. А во-вторых, изучение различных параметров компилятора выручит вас, когда средства вашего редактора не позволят вам полностью контролировать этот этап.
Если исходный код готов, откройте командное окно и установите текущей папку с файлом Hello World.cs. Теперь наберите строку:
esc helloWorld.cs
При правильной работе вы должны увидеть название и версию компилятора, информацию об ошибках и предупреждения (рис. 3-2). Кстати, как видите, на момент создания этого примера я использовал бета-версию компилятора. Независимо от версии вашего компилятора в результате компиляции этого примера вы не увидите ни ошибок, ни предупреждений.
Рис. 3.2. Результат успешной компиляции HelloWorld.cs.
Сообщение об ошибке " ' sc' is not recognized as an internal or external command, operable program or batch file" (" 'esc' не опознана как внутренняя или внешняя команда, действующая программа или пакетный файл") может означать, что вы не установили .NET SDK, который включает в себя компилятор С#.
Если при запуске компилятора С# допущена ошибка (скажем, неверно указано имя файла) или в качестве аргумента вы набрали ключ /?, компилятор выведет полный список параметров для компиляции приложения. Мне не хотелось бы останавливаться на описании всех ключей компилятора, поэтому сосредоточусь на самом важном, оставив вам остальное для самостоятельного изучения.
Итак, приложение "Hello, World" собрано — запустим его, чтобы убедиться, что приложения в .NET запускаются правильно. Все демонстрационные примеры в книге являются "консольными приложениями", так как главным для нас является С#, а не специфика Windows. Это позволит запускать их как из командной строки, так и из редактора, если в нем есть поддержка такого запуска.
Для запуска приложения из командной строки откройте командное окно и, установив текущей папку, где вы собрали приложение, введите строку HelloWorld. Вы увидите примерно следующее:
d:\>HelloWorld Hello, World
Если при запуске приложения из редактора вы не успели ничего увидеть, дополните свой код строкой:
class HelloWorld
{
public static void Main()
{
System.Console.WriteLine("Hello, World");
String str = System.Console.ReadLine(); }
Вызов System.Console.ReadLine переведет приложение в состояние ожидания, пока вы не нажмете клавишу Enter, дав таким образом возможность увидеть результат запуска. В других демонстрационных программах этой строки вы не встретите. Поэтому, запуская их из своего редактора, вставляйте ее перед концом каждого приложения.
Писать и запускать Си-приложение вы научились. Теперь посмотрим сам код и постараемся уяснить, что лежит в основе структуры любого С#-приложения.
В предыдущих главах и в приложении "Hello, World" вы могли заметить, что описания методов класса находятся внутри описания самого класса. Это не моя прихоть, как могли бы решить программисты на C++. Да, при написании программ на C++ у вас есть выбор: или поместить реализацию функций-членов класса прямо в объявлении класса — пример Mine-программирования, или разместить объявление класса и описания его функций-членов в разных файлах. В С# такого выбора у вас нет.
Описание класса в С# должно содержать встроенное (inline) описание всех методов — в этом языке заголовочных файлов не бывает. Благодаря этому правилу разработчики классов могут создавать высоко мобильный код, что является одной из ключевых концепций среды .NET. Создавая С#-класс, в конце концов вы имеете полностью инкапсулированную связку функциональных возможностей, которую можно легко перенести в любую среду разработки, и вам не надо беспокоиться, как в другом языке обрабатываются включаемые файлы и существует ли в нем вообще механизм включения файлов. Такой подход — универсальное программирование ("one-stop programming"-) — позволяет, например, перебросить весь класс на страницу Active Server Pages (ASP), и он будет функционировать так, будто был скомпилирован для настольного приложения Windows!
Первое, что мы видим в основном С#-приложении, — это имя класса или пространства имен. Как сказано в главе 1, вам нужно выбрать имя класса, который описывает проблемную область, например, Invoice, PurchaseOrder или Customer. Начало и окончание описания класса отмечается фигурными скобками — открывающей и закрывающей соответственно. Все, что внутри них, считается частью класса. Заметьте: в нашем случае класс называется HelloWorld, а все, что есть в приложении, описано в контексте этого класса.
Все члены класса описываются внутри фигурных скобок: методы, поля, свойства, индексаторы (indexers), атрибуты и интерфейсы. В следующих главах вы познакомитесь с особенностями описания различных элементов языка С#.
Каждое С#-приложение должно иметь метод с именем Main, описанный в одном из его классов. Не имеет значения, в каком классе находится этот метод: классов, может быть столько, сколько нужно для вашего приложения. Главное, чтобы в каком-нибудь классе был метод с именем Main. Кроме того, этот метод должен быть описан как открытый (public) и статический (static). Ключевое слово public является модификатором доступа, который сообщает компилятору С#, что этот метод может вызвать кто угодно. Как вы видели в главе 1, ключевое слово static означает, что метод является глобальным и что для его вызова не требуется создавать экземпляр этого класса. Это очень важно, так как иначе компилятор не знал бы, как или когда создавать экземпляр вашего класса. Раз метод статический, компилятор сохранит адрес метода как точку входа, и среда .NET начнет с него выполнение вашего приложения.
ПРИМЕЧАНИЕ
В примерах этой главы метод Main возвращает значение типа void и не имеет аргументов. Вы можете написать свой метод Main, который возвращает какое-то значение и имеет массив аргументов. Об этих возможностях, а также о том, как организовать циклический просмотр аргументов в методе Main, см. главу 5.
Метод System.Console. WriteLine выводит строку — вместе с символом конца строки — на стандартное устройство вывода. Обычно, если вы не изменили какие-нибудь параметры или не настроили свой редактор на вывод данных в окно, метод будет выводить строку в консольное окно.
В главе 2 говорится, что библиотеки классов .NET Framework образуют иерархическую структуру пространств имен (namespaces). Это может привести к довольно длинным именам, если требуемый класс или тип имеет очень большую глубину вложения. Чтобы сократить ввод длинных имен, в С# введена директива using. Посмотрим работу этой директивы на примере. В нашем приложении "Hello, World" есть такая строка:
System.Console.WriteLine("Hello, World");
Ввод такого текста несложен, а представьте, что у вас большое приложение с обширным набором типов и классов. Директива using позволяет компилятору найти непонятный ему элемент, просматривая указанное пространство имен. В нашем примере директива using используется так:
using System;
class HelloWorld {
public static void Main()
{
Console.WriteLine("Hello, World");
} }
В ходе синтаксического анализа метода Console. WriteLine компилятор установит, что этот метод не описан. Поэтому он примется просматривать пространства имен, заданные директивой using, и, найдя описание метода в пространстве имен System, завершит компиляцию кода без ошибок.
Заметьте: директива using применима к пространствам имен, но не к классам. В нашем примере System является пространством имен, Console — классом, a WriteLine — статическим методом класса Console. Поэтому такой код неверен:
using System.Console; //ОШИБКА. Нельзя использовать
//директиву using по отношению к классу.
class HelloWorld {
public static void Main()
{
WriteLineC'Hello, World");
} }
Указывать класс в директиве using нельзя, но существует вариант директивы using, позволяющий создать псевдоним для класса:
using псевдоним = класс
Благодаря этой форме директивы using можно написать подобный код: using output = System.Console;
class HelloWorld {
public static void Main()
{
output.WriteLine("Hello, World");
} }
Благодаря такому гибкому инструменту вы сможете, применяя выразительные псевдонимы для классов с несколькими уровнями вложения в иерархии .NET, сделать свой код немного легче и для написания, и для сопровождения.
Посмотрим, что в большинстве случаев может послужить костяком С#-программы — кодом, по которому видна основная структура примитивного С#-приложения. Такой код можно записать в файл и использовать как шаблон для создания новых приложений. Учтите, в угловые скобки нужно вставить свою информацию.
using <пространство имен>
namespace <ваше дополнительное пространство имен>
class <ваш класо
{
public static void Main()
{
} }
Итак, что мы уже знаем? Как написать, откомпилировать и запустить С#-приложение. Кроме того, у нас есть базовая схема сборки С#-при-ложения. Что же нужно делать, когда с хорошими приложениями случаются неприятности? Сначала определим, что такое "неприятности" — это когда случается то, чего не ждешь. В программировании неприятности бывают двух сортов: ошибки периода компиляции и ошибки периода выполнения. Разберем по паре примеров каждого вида ошибок и посмотрим, как их исправить.
Когда компилятор, в том числе и компилятор С#, не может понять, что вы ему подсунули, он выводит сообщение об ошибке, и сборка вашего приложения прерывается. Введите следующий код в файл HelloErrors.cs и запустите компилятор:
using Syste;
class HelloErrors {
public static void Main() {
xConsole.WriteLine("Hello, World");
Console.Writel_inex("Hello, World"); } >
В результате компилятор выдаст следующее сообщение:
HelloErrors.cs(1,7): error CS0234:
The type or namespace name ' Syste' does not exist in the class or namespace "
(HelloErrors.cs(1,7): ошибка CS0234:
Имя типа или пространства имен ' Syste 1 не существует в данном классе или пространстве имен ")
Если учесть, что по умолчанию глобальное пространство имен имеется всегда, это сообщение говорит, что компилятор (по понятным причинам) не обнаружил ничего с именем Syste. Однако здесь нужно обратить внимание на то, что происходит, когда компилятор обнаруживает в коде синтаксические ошибки. Сначала выводится имя компилируемого в данный момент файла, за которым следуют номер строки и столбца позиции, в которую прокралась ошибка. Затем идет код ошибки — в данном случае, СS0234.
После кода ошибки дано ее краткое описание, которое помогает понять причину ошибки. Если же у вас остались вопросы, посмотрите дополнительные разъяснения в документации по .NET Framework SDK, которая устанавливается вместе c.NET Framework SDK. Оперативная справка, найденная по коду ошибки CS0234, выглядит так (рис. 3-3):
Рис. 3.3. Код ошибки, выданный С#-компилятором, поможет вам найти ее описание в оперативной справочной системе.
Обратите внимание на следующее обстоятельство. Хотя мы допустили в коде три ошибки (пространство имен System дано с ошибкой, неправильно указан класс Console и ошибка в написании метода WriteLine), компилятор сообщит только об одной из них. Дело в том, что некоторые ошибки вынуждают компилятор прервать процесс компиляции и вывести ошибки, накопленные к этому моменту. В данном случае компилятор останавливает свою работу из-за ошибки в директиве using, поскольку такая ошибка может стать причиной множества других. После того как вы правильно напишете имя System, компилятор доложит о местонахождении двух оставшихся ошибок.
Как сказано в главе 2, компилятор .NET не создает исполняемые ЕХЕ-и DLL-файлы в традиционном виде. Вместо машинного кода он вставляет в них декларацию (manifest) со списками типов и классов, включенных в файл, а также коды MSIL-инструкций, подлежащих компиляции и выполнению либо установочным приложением, либо исполняющей средой .NET посредством ЛТ-компиляторов (JITter).
Очень важно, что сгенерированный MSIL-код похож на язык ассемблера и может использоваться в качестве учебного пособия, показывающего, что сделал компилятор с вашим кодом. Поэтому я буду не раз "опускаться" до выходного MSIL-файла компилятора языка С#, чтобы показать, что происходит внутри кода, и объяснить, почему следует применять то или иное средство языка и как это надо делать. Для просмотра выходного MSIL-файла можно использовать дисассемблер Microsoft .NET Framework IL Disassembler (ILDASM), позволяющий открыть выполняемый .NET-файл (EXE или DLL) и изучить его пространства имен, классы, типы и код. В следующем разделе мы познакомимся с достоинствами ILDASM.
В диалоговом окне Run меню Start введите команду ildasm и щелкните ОК. Перед вами появится довольно невзрачного вида приложение с несколькими меню. В меню File выберите команду Open. В появившемся диалоговом окне File Open откройте папку с приложением HelloWorld.exe, которое вы создали чуть раньше, и выберите его. Как видите, работа с программой ILDASM сулит нам что-то интересное (рис. 3-4).
Заметьте, как представлен управляемый двоичный код в ILDASM. Ниже показаны значки, с помощью которых ILDASM показывает части .NET-приложения (рис. 3-5). Сравнив эти значки с представлением приложения "Hello, World" в ILDASM, можно заметить, что HelloWorld.exe состоит из декларации, одного класса (HelloWorld) и двух методов (конструктора класса и статического метода Main) и кое-какой информации о классе.
В приложении "Hello, World" наиболее интересен метод Main. Дважды щелкните значок метода Main в древовидной структуре приложения, и ILDASM выведет окно, отображающее MSIL-код метода Main (рис. 3-6).
Рис. 3.4. ILDASM позволяет вам погрузиться в дебри декларации и IL-кодов, из которых состоит ваше приложение.
Рис. 3.5. Значки, которыми обозначаются в ILDASM разные части .NET-приложения.
Рис. 3.6. Чтобы увидеть MSIL-код метода, откройте двоичный файл в ILDASM и дважды щелкните этот метод.
Даже в виде MSIL наше приложение не стало более привлекательным, зато теперь из него можно выудить нечто такое, что характерно для любого .NET-приложения. Разберем-ка этот метод по косточкам.
.method public hidebysig static void Main() 11 managed {
.entrypoint
// Code size 11 (Oxb)
.maxstack 8
IL_0000: Idstr "Hello, World"
IL_0005: call void [mscorlib]System.Console:iWriteLine (class System.String)
IL_OOOa: ret }// end of method HelloWorld::Main
Первая строка содержит описание метода Main с помощью ключевого слова .method. Можно заметить, что в этом описании есть модификаторы public (открытый) и static (статический), устанавливаемые для Main по умолчанию. Кроме того, метод имеет атрибут managed (управляемый код). Это важная отличительная особенность, так как на С# можно создать и "неуправляемый" (unmanaged), или "небезопасный" (unsafe), код. Неуправляемому С#-коду посвящена глава 17.
Ключевое слово .entrypoint в следующей строке MSIL-кода указывает на то, что данный метод является точкой входа приложения. Когда исполняющая среда запускает приложение, управление программой передается коду, следующему за этой точкой.
Вызывают интерес и исполняемые коды в строках IL_0000 и IL_0005. В первой команда Idstr (Load String) загружает в стек неизменяемый литерал ("Hello, World"). В следующей строке вызывается метод System.Con-sole. WriteLine. Заметьте: к имени метода добавлено имя сборки (assembly), в которой описан метод. Такой уровень детализации MSIL хорош тем, что вы без труда напишете утилиту которая выявит связи в программе и отобразит информацию о файлах, требующихся для правильной работы приложения. Кроме того, вы можете определить число аргументов метода и их типы. В нашем случае метод System.Console. WriteLine принимает объект System.String, который перед вызовом метода должен быть помещен в стек. И, наконец, в строке IL_OOOa находится исполняемый MSIL-код ret — код возврата из метода.
ILDASM — мощный инструмент. Когда я упоминаю MSIL-код, сгенерированный компилятором С#, вы можете запустить ILDASM и увидеть, что я имею в виду.
ПРИМЕЧАНИЕ
Чтобы выяснить, какой код находится в файле ЕХЕ или DLL — управляемый или нет, попробуйте открыть его в ILDASM. Файл, содержащий MSIL-код и декларацию, будет открыт. В ином случае вы получите сообщение об ошибке, начинающееся фразой "<ваш файл > has no valid CLR header and cannot be disassembled-" (<ваш файл> не имеет надлежащего CLR-заголовка и не может быть дизассемблирован).
Эту главу я завершу рекомендациями по созданию приложений на С#.
В приложении "Hello, World" мы обращались к методу Console. WriteLine, описанному в пространстве имен System. Фактически описания всех типов и классов .NET находятся в пространствах имен. Для своего приложения мы не создавали пространства имен, поэтому остановимся на этом вопросе.
Пространства имен — прекрасный способ распределить типы и классы по категориям, исключив конфликты имен. Microsoft размещает все типы и классы .NET в специальных пространствах имен, стремясь защитить их от конфликтов с другими именами. Нужны ли собственные пространства имен? Это зависит от ответа на вопрос: будут ли создаваемые вами типы и классы использоваться в среде, которой вы не управляете? Иначе говоря, если ваш код крутится внутри ограниченного круга разработчиков, можно обойтись своими правилами создания имен, не допуская появления конфликтов. Но если ваши классы предназначены для применения вне вашей организации и контролировать ситуацию с именами вы не сможете, без собственных пространств имен не обойтись. Кроме того, поскольку Microsoft рекомендует указывать имя вашей компании в качестве пространства имен верхнего уровня, я советовал бы (бесплатно!) всегда создавать пространства имен в случаях, когда с вашим кодом может столкнуться другой разработчик.
По статистике наибольшие затраты, связанные с разработкой приложений, приходятся на его сопровождение. Прежде чем мы продолжим, мне хотелось бы рассказать о соглашениях по составлению имен, поскольку от простоты и понятности такого соглашения может зависеть читабельность и, следовательно, удобство сопровождения кода.
Многие из нас знают, что соглашения об именах — болезненная тема. Этот вопрос решался проще, пока не появились Visual C++ и MFC. Впервые я столкнулся с этой проблемой, когда группа, в которой я был ведущим разработчиком, получила задание создать первое в нашей компании Peachtree Software бухгалтерское приложение в среде MFC. Это было одно из тех собраний в самом начале проекта, когда все рвутся вперед и готовы, не жалея сил, идти до конца, в отличие от стадии завершения проекта, когда остается единственное желание — побыстрее сплавить эту проклятую программу. Разработчики шли плотным строем, глаза блестят — было ясно, что ребята готовы ринуться вперед. Что мне оставалось делать перед угрозой предстоящего кровавого побоища? Я сделал ход конем! Я решил, что, поскольку многое из MFC проникло в код Microsoft, мы должны использовать соглашения об именах Microsoft, принятые при создании MFC. В конце концов было бы весьма неразумно иметь две системы наименований в исходном коде: одну для MFC и другую для себя. Конечно, тот факт, что мне нравится венгерская нотация, даже и не затрагивался.
Однако сейчас другое время, и в лице С# мы имеем новый язык и новые задачи. В этой среде мы не видим кода Microsoft. Более того, после многих разговоров в Microsoft с группой проектировщиков С# я понял, что появляется некий стандарт. Возможно, он будет отличаться от того, что я представляю здесь, но это хотя бы даст вам точку опоры.
Прежде чем обсуждать вопросы, связанные с конструированием имен для различных элементов вашего приложения, вспомним стандарты, имеющиеся к настоящему времени.
Венгерская нотация
Венгерскую нотацию использует большинство разработчиков на С и C++ (включая и М1сго5ой'овцев). Эта система формирования имен создана сотрудником Microsoft Чарльзом Симони (Charles Simonyi). В начале 1980-х Microsoft приняла на вооружение систему, основа которой взята из докторской диссертации Симони "Meta-Programming: A Software Production Method" ("Мета-программирование: способ производства программного обеспечения").
Согласно венгерской нотации к имени переменной добавляется приставка, показывающая ее тип. Однако не каждый тип имеет свой стандартный префикс. Кроме того, появление новых языков и новых типов требует создания новых приставок. Поэтому немудрено, что со временем мы станем сталкиваться с префиксами, которые никогда нам раньше не встречались. (Между прочим, термин "Венгерская нотация" как бы показывает, что префиксы делают переменные такими, как будто они написаны на языке, отличном от английского; к тому же г-н Симонии родом из Венгрии.)
Возможно, наиболее важной публикацией, агитирующей в пользу венгерской нотации, была первая книга, которую прочитал почти каждый разработчик под Windows и OS/2. Это книга Чарльза Петцольда (Charles Petzold) "Programming Windows" (Microsoft Press), в которой один из диалектов венгерской нотации применяется во всех демонстрационных приложениях. Более того, и Microsoft пользуется этой системой обозначений в собственных разработках. С MFC родилась очередная серия специфичных для C++ префиксов, продлив жизнь венгерской нотации. Так почему бы и нам не продолжить применение венгерской нотации? Тем более что эта система обозначений удобна в ситуациях, где желательно знать тип и/или область видимости применяемой переменной. Однако, как вы узнаете в главе 4, все типы в С# являются объектами и основаны на .NET-классе System.Object. Поэтому все переменные имеют основной набор функциональных возможностей и поведенческих характеристик. Поэтому венгерская нотация в среде .NET теряет свою привлекательность.
ПРИМЕЧАНИЕ
Любопытные и те, кто страдает от бессонницы, могут почитать материалы о венгерской нотации по адресу http://msdn.microsqft.com/library/techart/hunganotat. htm.
Стили "Паскаль" и "верблюд"
Разработчики С# не связаны "жестким" стандартом, но из уже созданного ими видно, что они следуют набору условных обозначений, придуманных сотрудником Microsoft Робом Кэроном (Rob Caron), предложившим при обозначении переменных использовать смесь техник "Паскаль" и "верблюд". В статье "Coding Techniques and Programming Practices" ("Технологии и практика программирования"), имеющейся в MSDN ( http://msdn.microsoft.com/library/techart/cfr.htm), он предлагает для имен методов применять технику "Паскаль", где первый символ изображается прописной буквой, и для имен переменных — технику "верблюд". В демо-приложениях этой книги я так примерно и поступаю. Поскольку же в С# есть не только переменные и методы, в следующих разделах вы найдете перечень других элементов языка и соответствующих им нотаций.
ПРИМЕЧАНИЕ
Дополнительные сведения по этой теме см. в руководстве по .NET Framework, включенному в документацию по .NET Framework SDK, в разделе .NET Framework Developer Specificati-ons\.NET Framework Design Guidelines\Naming Guidelines.
Пространства имен
Название пространства имен должно соответствовать имени вашей компании или названию программы, и первая буква должна быть прописной, например, Microsoft. Если же вы занимаетесь распространением компонентов ПО, назовите пространство имен верхнего уровня именем вашей компании, а для каждого продукта создайте пространство имен следующего уровня со своими вложенными типами, исключив тем самым конфликты имен с другими продуктами. Пример тому есть в .NET Framework SDK: Microsoft. Win32. Такая техника приводит к нескончаемым цепочкам имен, однако благодаря директиве using пользователям вашего кода не придется вводить их целиком. Так, если компания Trey Research распространяет два продукта — электронную таблицу (grid) и базу данных (database), пространства имен будут иметь названия Тгеу-Research.Grid и Trey Research. Database.
Классы
Поскольку объекты являются как бы живыми, дышащими организмами, наделенными некоторыми способностями, в названиях классов применяйте имена существительные, которые описывают предметную область класса. Если класс представляет более общее понятие (т. е. не определяется только спецификой предметной области), например, при создании типа SQL-строки, используйте технику "Паскаль".
Методы
Применяйте технику "Паскаль" для всех методов. От методов ожидают выполнения некоей работы. Поэтому пусть в именах методов отражается то, что они делают. Например, Printlnvoice или OpenDatabase.
Если методы предполагается использовать в булевских выражениях, добавьте к имени метода глагол, указывающий на то, что метод будет делать. Например, если метод будет возвращать булевское значение, определяемое блокировкой рабочей станции, назовите метод вроде IsWorkStationLocked. Тогда при использовании метода в условном операторе его назначение будет понятнее, например:
if (IsWorkStationLocked) ...
Аргументы метода
Применяйте технику "Паскаль" для всех аргументов. Называйте аргументы выразительно, чтобы при работе IntelliSense пользователь мог сразу понять, для чего нужен каждый аргумент.
Интерфейсы
Применяйте технику "Паскаль" для всех интерфейсов. Стало традицией добавлять к имени интерфейса прописную букву "I", например, Кот-рагаЫе. (Это соглашение, пожалуй, единственное в С#, хоть как-io соответствующее венгерской нотации.)
Многие разработчики применяют одни и те же правила формирования имен и для интерфейсов и для классов. Однако между этими элементами существует фундаментальное философское различие. Классы представляют собой инкапсуляцию данных и функций, работающих с этими данными. Интерфейсы же представляют поведение объекта. Делая реализацию интерфейса, вы заявляете о готовности некоего класса продемонстрировать такое поведение. Поэтому в именах интерфейсов принято употреблять имена прилагательные. Например, интерфейс, объявляющий методы упорядочения данных, можно назвать таким образом: ISerializable.
Члены класса
Для разработчиков на С# это, пожалуй, самый неприятный вопрос. Те, кто работал с C++ и MFC, привыкли добавлять к именам членов приставку т_. Однако я советую вам обратиться к технике "верблюда", в которой первая буква не является прописной. Если у вашего метода есть аргумент Foo, то согласно этой технике вы сможете отличить его от внутреннего представления переменной, создав внутренний член/оо.
Не стоит добавлять к имени переменной имя класса. Пусть, например, есть класс Author. Можно создать член этого класса с именем Author-Name, но тогда его полное имя будет Author.AuthorName. Тогда как достаточно назвать этот член просто Name.
Подведем итоги
Написание, компиляция и выполнение Сопрограммы — первый важный шаг в освоении языка. Вообще-то неважно, чем вы редактируете исходные файлы, однако лучше всего воспользоваться преимуществами редактора и среды разработки, предназначенных специально для С#. Знание параметров и ключей С#-компилятора позволит вам управлять процессом создания MSIL-кода, генерируемого компилятором. Этот код можно изучить с помощью такого инструмента, как ILDASM из пакета Microsoft .NET Framework SDK.
В структуре программ на С# заложены средства, делающие программы надежными и простыми в написании, в том числе пространство имен и директива using. А правила формирования имен, включающие особые соглашения о регистрах букв, могут сделать программы более легкими для понимания и дальнейшего сопровождения.