ГЛАВА 1. Философия .NET
Каждые несколько лет программист должен быть готов кардинально обновлять свои знания, чтобы идти в ногу с новыми технологиями. Языки (C++, Visual Basic 6.0, Java), каркасы приложений (MFC, ATL, STL) и архитектуры (COM, CORBA, EJB), которые сегодня составляют "золотой фонд" разработки программного обеспечения, в будущем непременно уступят место чему-то более совершенному или, по крайней мере, более новому. Несмотря на разочарование, которое вы можете ощущать при обновлении своей базы знаний, это неизбежно. Платформа .NET - это сегодняшнее предложение Microsoft в области разработки программного обеспечения.
Целью этой главы является построение концептуального фундамента, необходимого для успешного освоения всего остального материала книги. Слава начинается с обсуждения ряда вопросов .NET, относящихся к высокому уровню, – таких как компоновочные блоки, CIL (общий промежуточный язык) и JIT-компиляция (just-in-time – точно к нужному моменту). Вдобавок к вводному обзору некоторых ключевых возможностей языка программирования C#, будет также обозначена взаимосвязь между различными элементами каркаса .NET, такими как CLR (общая языковая среда выполнения), CTS (общая система типов) и CLS (общие спецификации языка). Как вы вправе ожидать, эти темы будут исследоваться более подробно в других частях книги.
Эта глава также содержит обзор возможностей, предлагаемых библиотеками базовых классов .NET, для обозначения которых иногда используют аббревиатуру BCL (Base Class Libraries – библиотеки базовых классов) или, как альтернативу, FCL (Framework Class Libraries – библиотеки каркасных классов). Наконец, в главе обсуждается независимая от языков и платформ сущность платформы .NET (это действительно так - .NET не замыкается на операционной системе Windows).
Предыдущее состояние дел
Перед рассмотрением специфики .NET будет полезно рассмотреть некоторые проблемы, стимулировавшие появление предлагаемой сегодня платформы Microsoft. Чтобы получить соответствующее представление, давайте начнем эту главу с краткого урока истории, чтобы напомнить об истоках и понять ограничения, существовавшие в прошлом (в конце концов, признание существования проблемы является первым шагом на пути ее решения). После этого мы обратим наше внимание на многочисленные преимущества, которые обеспечиваются языком C# и платформой .NET.
Подход C/Win32 API
Традиционно разработка программного обеспечения для операционных систем семейства Windows предполагает использование языка программирования C в сочетании с Windows API (Application Programming Interface – интерфейс программирования приложений). Несмотря на тот факт, что в рамках этого проверенного временем подхода было создано очень много вполне успешных приложений, мало кто станет оспаривать то, что процесс создания приложений непосредственно с помощью API оказывается очень трудоемким делом.
Первая очевидная проблема заключается в том, что C является очень лаконичным языком. Разработчики программ на языке C вынуждены "вручную" управлять памятью, использовать безобразную арифметику указателей и ужасные синтаксические конструкции. К тому же, поскольку C является структурным языком программирования, ему не хватает преимуществ, обеспечиваемых объектно-ориентированным подходом (здесь можно вспомнить о "макаронных" программах). Когда вы объединяете тысячи глобальных функций и типов данных, определенных в рамках Win32 API, с языком, который и без того выглядит устрашающе, не следует удивляться тому, что среди используемых сегодня программ оказывается так много ненадежных.
Подход C++/MFC
Огромным шагом вперед по сравнению с подходом, предполагающим использование C/API, явился переход к применению языка программирования C++. Во многих отношениях язык C++ можно рассматривать, как объектно-ориентированную надстройку над C. Поэтому, хотя при использовании C++ уже можно использовать преимущества известных "краеугольных камней ООП" (инкапсуляция, наследование и полиморфизм), этот подход оставляет программиста во власти многих болезненных аспектов языка C (управление памятью "вручную", безобразная арифметика указателей и ужасные синтаксические конструкции).
Несмотря на сложность, сегодня существует множество каркасов программирования на C++. Например, MFC (Microsoft Foundation Classes – библиотека базовых классов Microsoft) снабжает разработчика набором C++-классов, упрощающих создание Win32-приложений. Главной задачей MFC является представление "разумного подмножества" Win32 API в виде набора классов, "магических" макросов и средств автоматического генерирования программного кода (обычно называемых мастерами). Несмотря на очевидную пользу указанного каркаса приложений (как и многих других средств разработчика, использующих C++), программирование на C++ остается трудной задачей, и на этом пути нелегко полностью избежать ошибок ввиду "тяжелой наследственности", обусловленной связью с языком C.
Подход Visual Basic 6.0
Благодаря искреннему желанию насладиться более простой жизнью, многие программисты ушли от "мира каркасов" приложений на базе C(++) к более дружественным языкам, таким, как, например, Visual Basic 6.0 (VB6). Язык VB6 стал популярным благодаря тому, что он дает возможность строить сложные интерфейсы пользователя, библиотеки программного кода (например, COM-серверы) и системы доступа к данным, затрачивая минимум усилий. В сравнении с MFC, VB6 еще глубже скрывает от глаз разработчика сложность Win32 API, используя для этого целый ряд интегрированных мастеров, внутренних типов данных, классов и специфических для VB функций.
Главным недостатком VB6 (который был устранен в Visual Basic .NET) является то, что VB6 является, скорее, "объектно-осведомленным" языком, а не полноценным объектно-ориентированным. Например, в VB6 программисту не позволяется связывать типы отношениями "подчиненности" (т.е. нет классического наследования) и нет внутренней поддержки конструкции параметризованных классов. Кроме того, VB6 не дает возможности строить многопоточные приложения, если только вы не готовы "спуститься" до низкоуровневых вызовов Win32 API (что в лучшем случае достаточно сложно, а в худшем – опасно).
Подход Java/J2EE
Было предложено использовать Java. Язык программирования Java является (почти) полностью объектно-ориентированным и имеет синтаксические корни в C++. Многие знают, что поддержка межплатформенной независимости – далеко не единственное преимущество Java. Java (как язык) избавлен от многих синтаксических несообразностей C++. Java (как платформа) предлагает программисту большое число встроенных "пакетов", содержащих различные определения типов. С помощью этих типов, используя "только Java", можно строить приложения, предлагающие сложный интерфейс пользователя, обеспечивающие связь с базами данных, обмен сообщениями или работу клиента в Web.
Хотя Java – очень элегантный язык, его потенциальной проблемой является то, что использование Java в цикле разработки обычно означает необходимость использования Java и для взаимодействия клиента с сервером. Как следствие, Java не позволяет возлагать большой надежды на возможности языковой интеграции, так как это идет вразрез с декларируемой целью Java (единый язык программирования для всех задач). Реальность, однако, такова, что в мире существуют миллионы строк программного кода, которым бы идеально подошло взаимодействие с более новым программным кодом. К сожалению, Java делает эту задачу проблематичной.
Java в чистом виде просто не подходит для многих приложений, интенсивно использующих графику или сложные вычисления (в этих случаях скорость работы Java оставляет желать лучшего). Для таких программ в соответствующем месте выгоднее использовать язык более низкого уровня (например, C++). Увы, пока Java не обеспечивает более широкие возможности доступа к "чужеродным" API, истинная интеграция различных языков оказывается практически невозможной.
Подход COM
Модель COM (Component Object Model – модель компонентных объектов) была предыдущим каркасом разработки приложений Microsoft. По сути, COM – это архитектура, "заявившая" следующее: если класс будет построен в соответствии с правилами COM, то получится блок двоичного кода многократного использования.
Прелесть двоичного COM-сервера в том, что способ доступа к нему не зависит от языка. Поэтому программисты, использующие C++, могут строить COM-классы, пригодные для использования в VB6. Программисты, применяющие Delphi, могут использовать COM-классы, построенные с помощью C, и т.д. Однако, и вы, возможно, об этом знаете, независимость COM от языка несколько ограничена. Например, нет возможности получить новый COM-класс из уже существующего (поскольку COM не предлагает поддержки классического наследования). Вместо этого для использования типов COM-класса вам придется указать несколько неуклюжее отношение "обладания".
Еще одним преимуществом COM является прозрачность дислокации. Используя такие конструкции, как идентификаторы приложения (AppID), "заглушки" и "заместители" в среде выполнения COM, программист может избежать необходимости непосредственного обращения к сокетам, RPC-вызовам и другими низкоуровневым элементам. Рассмотрим, например, следующий программный код VB6 COM-клиента.
' Этот блок программного кода VB6 может активизировать COM-класс,
' созданный на любом языке, поддерживающем COM, и размещенный
' в любой точке сети (включая вашу локальную машину).
Dim с as MyCOMClass
Set с = New MyCOMClass ' Размещение выясняется с помощью AppID.
с.DoSomeWork
Хотя COM можно считать очень успешной объектной моделью, внутренне она чрезвычайно сложна (по крайней мере, пока вы не потратите несколько месяцев на изучение ее внутренних механизмов – особенно если вы программируете на C++). С целью упрощения процесса разработки бинарных COM-объектов было создано множество каркасов разработки приложений с поддержкой COM. Среди них, например, библиотека ATL (Active Template Library – библиотека активных шаблонов), которая обеспечивает еще одно множество C++-классов, шаблонов и макросов, упрощающих создание COM-типов.
Многие другие языки также в значительной степени скрывают инфраструктуру COM от глаз программиста. Однако поддержки самого языка оказывается недостаточно для того, чтобы скрыть всю сложность COM. Даже при использовании относительно простого совместимого с COM языка (например, VB6), вы все равно вынуждены бороться с "хрупкими" параметрами регистрации и многочисленными проблемами, связанными с инсталляцией приложений (в совокупности называемыми "кошмаром DLL").
Подход Windows DNA
Ко всем указанным выше сложностям еще добавляется такая мелочь, как Интернет. За последние несколько лет Microsoft добавила в свое семейство операционных систем и других продуктов множество связанных с Интернет возможностей. К сожалению, создание Web-приложений в рамках совместимой с COM архитектуры Windows DNA (Distributed interNet Applications Architecture – архитектура распределенных сетевых приложений) также оказывается очень непростым делом.
Некоторая доля этой сложности вытекает из того простого факта, что Windows DNA требует использования множества технологий и языков (ASP, HTML, XML, JavaScript, VBScript, а также COM(+) и API доступа к данным, например ADO).
Одной из проблем является то, что с синтаксической точки зрения многие из этих технологий совершенно не связаны одна с другой. Например, в JavaScript используется синтаксис, во многом подобный C, a VBScript является подмножеством VB6. COM-серверы, созданные для работы в среде выполнения COM+, по виду сильно отличаются от ASP-страниц, которые их вызывают. Результат – чрезвычайно запутанная смесь технологий.
К тому же, и это, возможно, самое важное, каждый язык и каждая технология имеют свои собственные системы типов (которые могут быть совершенно не похожими одна на другую). Например, нельзя сказать, что "int" в JavaScript и "Integer" в VB6 означают в точности одно и то же.
Решение .NET
Слишком много для короткого урока истории. Основным выводом является то, что жизнь программиста Windows была трудна. Каркас .NET Framework является достаточно радикальной "силовой" попыткой сделать нашу жизнь легче. Решение, предложенное .NET, предполагает "изменить все" (извините, вы не можете обвинять посыльного за такое известие). Вы поймете из дальнейшего материала книги, что .NET Framework – это совершенно новая модель для создания систем как в семействе операционных систем Windows, так и множестве операционных систем, отличных от систем Microsoft, таких как Mac OS X и различные варианты Unix/ Linux. Чтобы это продемонстрировать, вот вам краткий список некоторых базовых возможностей, обеспечиваемых .NET.
• Полноценная возможность взаимодействия с существующим программным кодом. Это (конечно) хорошо. Существующие бинарные COM-объекты могут комбинироваться (т.е. взаимодействовать) с более новыми бинарными .NET-объектами и наоборот. Кроме того, сервисы PInvoke (Platform Invocation Services – сервисы вызова платформ) позволяют вызывать библиотеки на базе C (включая API операционной системы) из программного кода .NET.
• Полная и тотальная интеграция языков. В отличие от COM, платформа .NET поддерживает межъязыковое наследование, межъязыковую обработку исключений и межъязыковую отладку.
• Общий механизм выполнения программ для всех языков с поддержкой .NET. Одной из особенностей этого механизма является четкий набор типов, "понятных" каждому языку.
• Библиотека базовых классов. Эта библиотека позволяет избежать сложностей прямого обращения к API и предлагает согласованную объектную модель, используемую всеми языками с поддержкой .NET.
• Отсутствие детализации COM. В собственном бинарном .NET-объекте небудет места для IClassFactory, IUnknown, IDispatch, IDL-кода и "злобных" типов данных наподобие VARIANT (BSTR, SAFEARRAY и т.д.).
• Упрощенная модель инсталляции. Согласно спецификациям .NET, нет необходимости регистрировать соответствующую бинарную единицу в реестре системы. К тому же .NET вполне допускает существование множества версий одного *.dll на одной машине.
На основе информации этого списка вы, вероятно, уже сами пришли к заключению, что платформа .NET не имеет ничего общего с COM (за исключением того, что оба эти каркаса разработки приложений исходят из Microsoft). Фактически единственным способом взаимодействия типов .NET и COM оказывается использование возможностей слоя взаимодействия.
Замечание. Описание возможностей слоя взаимодействия .NET (включая Plnvoke) выходит за рамки этой книги. Если вам потребуется подробное освещение этого вопроса, обратитесь к моей книге COM and .NET Interoperability (Apress, 2002).
Главные компоненты платформы .NET (CLR, CTS и CLS)
Теперь, когда вы знаете о некоторых преимуществах, обеспечиваемых .NET, давайте рассмотрим три ключевых (и взаимосвязанных) компонента, которые и обеспечивают эти преимущества: CLR, CTS и CLS. С точки зрения программиста .NET может интерпретироваться как новая среда выполнения программ и всеобъемлющая библиотека базовых классов. Слой среды выполнения здесь называется CLR (Common Language Runtime – общеязыковая среда выполнения). Главной задачей CLR являются размещение, загрузка и управление .NET-типами по вашему указанию. Кроме того, CLR отвечает за ряд низкоуровневых вопросов, таких, как, например, управление памятью и проверка безопасности.
Другим строительным блоком платформы.NET является CTS (Common Type System – общая система типов). Спецификации CTS полностью описывают все возможные типы данных и программные конструкции, поддерживаемые средой выполнения, указывают, как эти элементы могут взаимодействовать друг с другом и как они представляются в формате метаданных .NET (более подробная информация о метаданных будет представлена немного позже).
Вы должны понимать, что конкретный язык, совместимый с .NET, может и не поддерживать абсолютно все возможности, определенные CTS. В связи с этим используются связанные спецификации CLS (Common Language Specification – общеязыковые спецификации), которые определяют подмножество общих типов и программных конструкций, понятных всем языкам программирования, совместимым с .NET. Поэтому, если создаваемые вами .NET-типы опираются только на возможности, соответствующие CLS, вы можете пребывать в уверенности, что использовать их сможет любой совместимый с .NET язык. А если вы используете типы данных или программные конструкции, выходящие за пределы CLS, вы не можете гарантировать, что с вашей библиотекой программного .NET-кода сможет взаимодействовать любой язык программирования .NET.
Роль библиотек базовых классов
В дополнение к спецификациям CLR и CTS/CLS, платформа .NET предлагает библиотеку базовых классов, доступную всем языкам программирования .NET. Эта библиотека базовых классов не только инкапсулирует различные примитивы, такие как потоки, файловый ввод-вывод, визуализация графики и взаимодействие с различными внешними устройствами, но и обеспечивает поддержку целого ряда сервисов, необходимых для большинства современных приложений.
Например, библиотеки базовых классов определяют типы, упрощающие доступ к базам данных, работу с XML, поддержку программной безопасности и создание Web-приложений (а также обычных настольных и консольных приложений) клиента. Схема высокоуровневых взаимосвязей между CLR, CTS, CLS и библиотекой базовых классов показана на рис. 1.1.
Рис. 1.1. CLR, CTS, CLS и библиотека базовых классов
Роль языка C#
С учетом того, что принципы .NET так радикально отличаются от предшествующих технологий, Microsoft разработала новый язык программирования, C# (произносится "си-диез"), специально для использования с этой новой платформой. Язык C# является языком программирования, по синтаксису очень похожим на Java (но не идентичным ему). Однако называть C# "переработанным" вариантом Java будет неверно. C#, как и Java, основан на синтаксических конструкциях C++. Так же, как и Java, C# можно называть "рафинированной" версией C++ – в конце концов, это языки одного семейства.
Многие синтаксические конструкции C# построены с учетом решений, принятых в Visual Basic 6.0 и C++. Например, как и в VB6, в C# поддерживаются формальные свойства типов (в противоположность традиционным методам get и set) и возможность объявления методов с переменным числом аргументов (через массивы параметров). Подобно C++, в C# позволяется перегрузка операций, а также создание структур, перечней и функций обратного вызова (посредством делегатов).
Благодаря тому, что C# является гибридом множества языков, он является продуктом, который синтаксически так же "чист", как Java (если не "чище"), почти так же прост, как VB6, и обладает почти такой же мощью и гибкостью, как C++ (без соответствующих "ужасных" конструкций). По сути, язык C# предлагает следующие возможности (многие из которых присущи и всем другим языкам программирования, обеспечивающим поддержку .NET).
• Не требуется никаких указателей! Программы на C# обычно не требуют прямого обращения к указателям (хотя имеется возможность получить к ним доступ на более низком уровне, если вы сочтете это абсолютно необходимым).
• Автоматическое управление памятью через сборку мусора. По этой причине в C# не поддерживается ключевое слово delete.
• Формальные синтаксические конструкции для перечней, структур и свойств классов.
• Аналогичная C++ перегрузка операций для пользовательских типов, но без лишних сложностей (например, вам не требуется контролировать "возвращение *this для связывания").
• В C# 2005 имеется возможность строить общие типы и общие члены с использованием синтаксиса, очень похожего на шаблоны C++.
• Полная поддержка техники программирования, основанной на использовании интерфейсов.
• Полная поддержка технологии аспектно-ориентированного программирования (АОП) через атрибуты. Эта ветвь разработки позволяет назначать характеристики типам и их членам, чтобы уточнять их поведение.
Возможно, самым важным для правильного понимания языка C#, поставляемого Microsoft в связке с платформой .NET, является то, что получаемый с помощью C# программный код может выполняться только в среде выполнения .NET (вы не сможете использовать C# для построения "классического" COM-сервера или автономного приложения Win32 API). Официальный термин, который используется для описания программного кода, предназначенного для среды выполнения .NET, – управляемый программный код (managed code). Бинарный объект, содержащий такой управляемый программный код, называется компоновочным блоком (подробнее о компоновочных блоках мы поговорим немного позже). С другой стороны, программный код, который не может непосредственно управляться средой выполнения .NET, называется неуправляемым программным кодом (unmanaged code).
Другие языки программирования с поддержкой .NET
Вы должны понимать, что C# является не единственным языком, ориентированным на платформу .NET. Когда платформа .NET была впервые представлена общественности на Профессиональной конференции разработчиков Microsoft в 2000 году, ряд производителей объявили, что они уже разрабатывают версии соответствующих компиляторов, совместимые с .NET. На момент создания этой книги десятки различных языков подверглись влиянию .NET. В дополнение к пяти языкам, которые предлагаются в Visual Studio 2005 (C#, J#, Visual Basic .NET, Managed Extensions для C++ и JScript .NET), имеются также .NET-компиляторы для Smalltalk, COBOL и Pascal (это далеко не полный перечень).
Материал этой книги почти исключительно посвящен языку C#, но в табл. 1.1 приводится список других языков программирования, совместимых с .NET, и указано, где найти более подробную информацию о них (учтите, что соответствующие адреса URL могут измениться).
Таблица 1.1. Некоторые из языков программирования, совместимых с .NET
Адрес Web-страницы языка .NET | Описание |
http://www.oberon.ethz.ch/oberon.NET | "Домашняя" страница Active Oberon .NET |
http://www.usafa.af.mil/df/dfcs/bios/mcc_html/a_sharp.cfm " | Домашняя" страница А# (порт Ada для платформы .NET) |
http://www.netcobol.com | Для тех, кого интересует COBOL .NET |
http://www.eiffel.com | Для тех, кого интересует Eiffel .NET |
http://www.dataman.ro/dforth | Для тех, кого интересует Forth .NET |
http://www.silverfrost.com/ll/ftn95/ftn95_fortran_95_for_windows.asp | Для тех, кого интересует Fortran .NET |
http://www.vmx-net.com | Оказывается, доступен даже Smalltalk .NET |
Следует учесть, что информация табл. 1.1 не является исчерпывающей. Списки компиляторов для .NET имеются на многих Web-узлах, и один из таких списков должен быть на странице http://www.dotnetpowered.com/languages.aspx (опять же, точный адрес URL может измениться). Я рекомендую посетить эту страницу, поскольку вас непременно заинтересуют хотя бы некоторые из языков .NET (может, кому-то понадобится LISP .NET).
Жизнь в многоязычном окружении
В начале процесса осмысления разработчиком языково-агностической природы платформы .NET, у него возникает множество вопросов и прежде всего, следующий: "Если все языки .NET при компиляции преобразуются в "управляемый программный код", то почему существует не один, а множество компиляторов?". Ответить на этот вопрос можно по-разному. Во-первых, мы, программисты, бываем очень привередливы, когда дело касается выбора языка программирования (я здесь тоже не исключение). Некоторые из нас предпочитают языки с многочисленными точками с запятыми и фигурными скобками, но с минимальным набором ключевых слов. Другим нравятся языки, предлагающие более "человеческие" синтаксические лексемы (как Visual Basic .NET). А кто-то не пожелает отказываться от своего опыта работы на большой ЭВМ и захочет перенести его на платформу .NET (используя COBOL .NET).
А теперь скажите честно: если бы Microsoft предложила единственный "официальный" язык .NET, например, на базе семейства BASIC, то все ли программисты были бы рады такому выбору? Или если бы "официальный" язык .NET был основан на синтаксисе Fortran, то сколько людей в мире вообще проигнорировало бы платформу .NET? Поскольку среда выполнения .NET демонстрирует меньшую зависимость от языка, используемого для построения управляемого программного кода, программисты .NET могут, не меняя своих синтаксических предпочтений, обмениваться скомпилированными компоновочными блоками со своими коллегами, другими отделами и внешними организациями (не обращая внимания на то, какой язык .NET используется там).
Еще одно полезное преимущество интеграции различных языков .NET в одном унифицированном программном решении вытекает из того простого факта, что каждый язык программирования имеет свои сильные (а также слабые) стороны. Например, некоторые языки программирования имеют превосходную встроенную поддержку сложных математических вычислений. В других лучше реализованы финансовые или логические вычисления, взаимодействие с центральными компьютерами и т.д. Когда преимущества конкретного языка программирования объединяются с преимуществами платформы .NET, выигрывают все.
Конечно, вы можете разрабатывать программное обеспечение, не выходя за рамки своего любимого языка .NET. Но, изучив синтаксис одного языка .NET, вам будет очень легко освоить любой другой. Это тоже очень выгодно, особенно консультантам. Если вашей специализацией является C#, но вы оказались на узле клиента, который "привязан" к Visual Basic .NET, то сможете почти сразу разобрать соответствующий программный код (поверьте!), воспользовавшись указанным преимуществом .NET. На этом и остановимся.
Компоновочные блоки .NET
Независимо от того, какой язык .NET вы выберете для программирования, вы должны понимать, что хотя бинарные .NET-единицы имеют такие же расширения файлов, как COM-серверы и неуправляемые программы Win32 (*.dll или *.exe), их внутреннее устройство совершенно иное. Например, бинарные .NET-единицы *.dll не экспортируют методы для упрощения коммуникации со средой выполнения COM (поскольку .NET – это не COM). Бинарные .NET-единицы не описываются с помощью библиотек COM-типов и не регистрируются в реестре системы. Наверное, самым важным является то, что бинарные .NET-единицы содержат не специфические для платформы инструкции, а независимые от платформы IL-инструкции (Intermediate Language – промежуточный язык) и метаданные типов. На рис. 1.2 это показано схематически.
Рис. 1.2. Все .NET-компиляторы генерируют IL-инструкции и метаданные
Замечание. Относительно сокращения "IL" здесь уместно сказать несколько дополнительных слов. В ходе разработки .NET официальным названием для IL было Microsoft (intermediate Language (MSIL). Однако в вышедшей версии .NET это название было изменено на OIL (Common Intermediate Language – общий промежуточный язык). Поэтому вам следует знать, что в публикациях, посвященных .NET, сокращения IL, MSIL и CIL обозначают одно и то же. В соответствии с терминологией, принятой сегодня, в тексте этой книги используется сокращение CIL.
После создания *.dll или *.exe с помощью подходящего .NET-компилятора, соответствующий модуль упаковывается в компоновочный блок. Подробное описание компоновочных блоков .NET имеется в главе 11. Однако, чтобы продолжить наше обсуждение среды выполнения .NET, вы должны знать основные особенности формата этих новых файлов.
Как уже было сказано, компоновочный блок содержит программный код CIL, который концептуально напоминает байт-код Java в том смысле, что он не компилируется в специфические для соответствующей платформы инструкции, пока это не станет абсолютно необходимо. Обычно "абсолютная необходимость" означает момент, когда на какой-то блок CIL-инструкций (например, реализацию метода) выполняется ссылка для его использования в среде выполнения .NET.
В добавление к CIL-инструкциям, компоновочные блоки также содержат метаданные, которые подробно описывают особенности каждого "типа" внутри данной бинарной .NET-единицы. Например, если вы имеете класс с именем SportsCar, соответствующие метаданные типа будут описывать такие элементы, как базовый класс SportsCar и интерфейсы, реализуемые SportsCar (если таковые имеются), а также содержать полные описания всех членов, поддерживаемых типом SportsCar.
Метаданные .NET более совершенны по сравнению с метаданными COM. Вы, возможно, уже знаете, что бинарные COM-объекты обычно описываются с помощью библиотеки ассоциированных типов, а это почти то же самое, что и бинарная версия IDL-кода (Interface Definition Language – язык определения интерфейса). Проблема использования COM-информации в том, что эта информация не обязательна, и IDL-код не может документировать внешние серверы, которые нужны для правильного функционирования данного COM-сервера. В противоположность этому метаданные .NET присутствуют обязательно и автоматически генерируются соответствующим .NET-компилятором.
Наконец, в добавление к CIL и метаданным типов, сами компоновочные блоки также описываются с помощью метаданных, для которых используют специальное называние манифест (manifest). Манифест содержит информацию о текущей версии компоновочного блока, информацию о "культуре" (используемую для локализации строк и графических ресурсов) и список всех ссылок на внешние компоновочные блоки, которые требуются для правильного функционирования. Из следующих глав вы узнаете о различных инструментах, которые могут использоваться для исследования типов компоновочного блока, расшифровки его метаданных и манифеста.
Одномодульные и многомодульные компоновочные блоки
Во многих случаях компоновочные блоки .NET- это просто файлы двоичного кода (*.dll или *.exe). Поэтому, если вы строите *.dll .NET, можно считать, что файл двоичного кода и компоновочный блок – это одно и то же. Точно также, если вы строите выполняемое приложение для настольной системы, файл *.exe тоже можно считать компоновочным блоком. Но из главы 11 вы узнаете, что указанное соответствие не столь однозначно. Строго говоря, если компоновочный блок состоит из одного модуля *.dll или *.exe, вы имеете одномодульный компоновочный блок. Одномодульный компоновочный блок содержит весь необходимый код CIL, метаданные и манифест в одном автономном отдельном пакете.
Многомодульные компоновочные блоки, в свою очередь, складываются из множества бинарных .NET-единиц, каждая из которых называется модулем. При этом один из таких модулей (он называется первичным модулем) должен содержать манифест компоновочного блока (и может содержать также CIL-инструкции и метаданные различных типов). Остальные связанные модули содержат манифест уровня модуля, CIL и метаданные типов. Как вы можете догадаться, в манифесте первичного модуля компоновочного блока документируется набор необходимых "второстепенных" модулей.
Но зачем создавать многомодульные компоновочные блоки? Когда вы делите компоновочный блок на отдельные модули, вы получаете более гибкие возможности инсталляции. Например, если пользователь ссылается на удаленный компоновочный блок, то среда выполнения загрузит на его машину только необходимые модули. Поэтому вы можете сконструировать свой компоновочный блок так, чтобы редко используемые типы (например, HardDriveReformatter) были выделены в отдельный автономный модуль.
Если все ваши типы размещаются в компоновочном блоке, представляющем собой единый файл, конечному пользователю придется загружать большой набор данных, из которых в действительности могут понадобиться далеко не все (а это, очевидно, означает лишнюю трату времени). Итак, компоновочный блок на самом деле логически сгруппирован в один или несколько модулей, которые должны инсталлироваться и использоваться, как единое целое.
Роль CIL
Теперь, когда вы имеете начальное представление о компоновочных блоках .NET, давайте немного подробнее обсудим роль общего промежуточного языка (CIL). CIL- это язык, находящийся выше любого набора инструкций, специфического для конкретной платформы. Независимо от того, какой язык .NET вы выберете для использования, соответствующий компилятор сгенерирует инструкции CIL. Например, следующий программный код C# моделирует тривиальный калькулятор. Не пытаясь пока что полностью понять синтаксис этого примера, обратите внимание на формат метода Add() в классе Calc.
// Calc.cs
using System;
namespace CalculatorExample {
// Этот класс содержит точку входа приложения.
public class CalcApp {
static void Main() {
Calc с = new Calc();
int ans = c.Add(10, 84);
Console.WriteLine("10 + 84 is {0}.", ans);
// Ждать, пока пользователь не нажмет клавишу ввода.
Console.ReadLine();
}
}
// C#-калькулятор.
public class Calc {
public int Add (int x, int y) {return x + y;}
}
}
После того как компилятор C# (csc.exe) скомпилирует этот файл исходного кода, вы получите состоящий из одного файла компоновочный блок *.exe, который содержит манифест, CIL-инструкции и метаданные, описывающие каждый аспект классов Calc и CalcApp. Например, если вы откроете этот компоновочный блок с помощью ildasm.exe (мы рассмотрим ildasm.exe немного позже в этой же главе), вы увидите, что метод Add () в терминах CIL представляется так.
.method public hidebysig instance int32 Add(int32 x, int32 y) cil managed
{
// Code size 8 (0x8)
.maxstack 2
.locals init ([0] int32 CS$l$0000)
IL_0000: ldarg.1
IL_0001: ldarg.2
IL_0002: add
IL_0003: stloc.0
IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
} // end of method Calc::Add
Не беспокойтесь, если вы пока не в состоянии понять CIL-код для этого метода – в главе 15 будут описаны основы языка программирования CIL. Здесь следует сконцентрироваться на том, что компилятор C# генерирует CIL-код, а не специфические для платформы инструкции.
Напомним теперь, что это верно для всех .NET-компиляторов. Для иллюстрации предположим, что вы создали аналогичное приложение с помощью Visual Basic .NET (VB .NET), а не с помощью C#.
' Calc.vb
Imports System
Namespace CalculatorExample
' VB .NET 'Модуль' – это класс, содержащий только ' статические члены.
Module CalcApp
Sub Main()
Dim ans As Integer
Dim с As New Calc
ans = c.Add(10, 84)
Console.WriteLine("10 + 84 is {0}.", ans)
Console.ReadLine()
End Sub
End Module
Class Calc
Public Function Add (ByVal x As Integer, ByVal у As Integer) As Integer
Return x + у
End Function
End Class
End Namespace
Если теперь проверить CIL-код для метода Add(), вы обнаружите подобные инструкции (слегка "подправленные" компилятором VB .NET).
.method public instance int32 Add(int32 x, int32 y) cil managed
{
// Code size 9 (0x9)
.maxstack 2
.locals init ([0] int32 Add)
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldarg.2
IL_0003: add.ovf
IL_0004: stloc.0
IL_0005: br.s IL_0007
IL_0007: ldloc.0
IL_0008: ret
} // end of method Calc::Add
Преимущества CIL
Вы можете спросить, зачем компилировать исходный код в CIL, а не прямо в набор специальных системных команд. Одним из преимуществ этого является интеграция языков, поскольку вы уже убедились, что все компиляторы .NET выдают приблизительно одинаковые наборы CIL-инструкций. Поэтому все языки могут взаимодействовать в рамках четко обозначенной двоичной "арены".
Кроме того, поскольку CIL демонстрирует независимость от платформы, каркас .NET Framework тоже оказывается независимым от платформы, обеспечивая то, к чему так привыкли разработчики Java (единую базу программного кода, способного работать во многих операционных системах). Фактически уже имеется международный стандарт для языка C#, а значительная часть платформы .NET реализована для множества операционных систем, отличных от Windows (более подробная информация об этом имеется в конце главы). Но, в отличие от Java, .NET позволяет строить приложения, используя язык вашего предпочтения.
Преобразование CIL-кода в набор инструкций, соответствующих платформе
Ввиду того, что компоновочные блоки содержат CIL-инструкции, а не инструкции для конкретной платформы, программный код CIL перед использованием приходится в фоновом режиме компилировать. Объект, который компилирует программный код CIL в инструкции, понятные процессору машины, называется JIT-компилятором (just-in-time – точно к нужному моменту), который иногда "по-дружески" также называют Jitter. Среда выполнения .NET использует JIT-компилятор, соответствующий конкретному процессору и оптимизированный для соответствующей платформы.
Например, если ваше .NET-приложение предназначено для выполнения на "компактном" устройстве (таком, как, например, КПК), то соответствующий JIT-компилятор будет иметь специальные средства для учета условий ограниченности памяти. Если это компоновочный блок для серверной системы (где объем памяти редко оказывается проблемой), то соответствующий JIT-компилятор будет оптимизирован для работы в условиях достаточного объема памяти. Таким образом разработчики получают возможность создавать только один блок программного кода, который с помощью JIT-компиляции можно выполнять на машинах с разной архитектурой.
К тому же, при компиляции CIL-инструкций в соответствующий машинный код JIT-компилятор поместит результаты компиляции в кэш в соответствии с тем, как этого требует соответствующая операционная система. Так, при первом вызове метода с именем PrintDocument() соответствующие CIL-инструкции компилируются в конкретные инструкции платформы и сохраняются в памяти для использования в дальнейшем. Поэтому при следующих вызовах PrintDocument () необходимости в повторной компиляции CIL не возникает.
Роль метаданных типов .NET
Кроме CIL-инструкций, компоновочный блок .NET содержит исчерпывающие и точные метаданные, описывающие все его типы (классы, структуры, перечни и т.д.), определенные в бинарном объекте, и все члены каждого типа (свойства, методы, события и т.д.). К счастью, задача создания метаданных всегда возлагается на компилятор (а не на программиста). По причине того, что метаданные .NET так подробны и точны, компоновочные блоки оказываются единицами, способными себя полностью описать, – настолько полно, что для бинарных .NET-объектов не возникает необходимости регистрироваться в реестре системы.
Для иллюстрации формата метаданных типов .NET давайте рассмотрим метаданные, сгенерированные для метода Add() C#-класса Calc, представленного выше (метаданные, генерируемые для VB .NET-версии метода Add(), оказываются аналогичными).
TypeDef #2 (02000003)
-----------------------------------------------------------
TypDefName: CalculatorExample.Calc (02000003)
Flags: [Public] [AutoLayout] [Class] [AnsiClass] [BeforeFieldlnit] (00100001)
Extends: 01000001 [TypeRef] System.Object
Method #1 (06000003)
-----------------------------------------------------------
MethodName: Add (06000003)
Flags: [Public] [HideBySig] [ReuseSlot] (00000086)
RVA: 0x00002090
ImplFlags: [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: I 4
2 Arguments
Argument #1: I4
Argument #2: I4
2 Parameters
(1) ParamToken: (08000001) Name: x flags: [none] (00000000)
(2) ParamToken: (08000002) Name: у flags: [none] (00000000)
Метаданные используются средой выполнения .NET, а также различными средствами разработки. Например, возможность IntelliSense, предлагаемая в Visual Studio 2005 в режиме проектирования, основана на чтении метаданных компоновочного блока. Метаданные используются различными утилитами просмотра объектов, инструментами отладки и самим компилятором C#. Для полноты картины заметим также, что использование метаданных лежит в основе множества .NET-технологий, включая удаленный доступ, отображение типов, динамическое связывание, Web-сервисы XML и сериализацию объектов.
Роль манифеста компоновочного блока
Наконец вспомним, что компоновочный блок .NET содержит также метаданные, описывающие сам компоновочный блок (эти метаданные называются манифест). Среди всего прочего, в манифесте документируются все внешние компоновочные блоки, которые требуются текущему компоновочному блоку для корректного функционирования, указан номер версии компоновочного блока, информация об авторских правах и т.д. Подобно метаданным типов, генерирование манифеста компоновочного блока тоже является задачей компилятора. Вот некоторые подходящие для иллюстрации элементы манифеста CSharpCalculator.exe.
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
.ver 2:0:0:0
}
.assembly CSharpCalculator
{
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module CSharpCalculator.exe
.imagebase 0x00400000
.subsystem 0x00000003
.file alignment 512
.corflags 0x00000001
По сути, этот манифест содержит указания на внешние компоновочные блоки, необходимые для CSharpCalculator.exe (для этого используется директива.assembly extern), а также различные характеристики самого компоновочного блока (номер версии, имя модуля и т.д.).
Общая система типов
Компоновочный блок может содержать любое число четко определенных "типов". В мире .NET "тип" – это просто общий термин, используемый для обозначения любого элемента из множества {класс, структура, интерфейс, перечень, делегат}. При построении решений с помощью любого языка .NET вы, скорее всего, будете взаимодействовать с каждым из этих типов. Например, компоновочный блок может определять один класс, в котором реализовано ряд интерфейсов. И, возможно, один из методов интерфейса будет принимать перечень в качестве входного параметра, а возвращать некоторую структуру.
Напомним, что CTS (общая система типов) – это формальное описание того, как должны определяться типы, подходящие для использования в среде CLR. Обычно внутренние механизмы CTS важны только тем, кто создает средства разработки и/или строит компиляторы для платформы .NET. Но для любого программиста .NET важно знать, как работать с пятью типами, определяемыми спецификациями CTS для выбранного разработчиком языка программирования. Ниже предлагается краткий обзор соответствующих вопросов.
Тип класса
Любой язык, совместимый с .NET, поддерживает, как минимум, тип класса, который является "краеугольным камнем" объектно-ориентированного программирования (ООП). Класс может состоять из любого числа членов (таких, как свойства, методы и события) и элементов данных (таких, как поля). В C# классы объявляются с помощью ключевого слова class.
// Тип класса C#.
public class Calc {
public int Add(int x, int y) {return x + y;}
}
Процесс построения типов класса CTS в C# будет рассматриваться в главе 4, но ряд общих характеристик типов класса приводится в табл. 1.2.
Таблица 1.2. Характеристики классов CTS
Характеристика класса | Описание |
Изолированность | Изолированные классы не могут быть базой для создания других классов, т.е. не позволяют наследование |
Наличие интерфейсов | Интерфейс - это набор абстрактных членов, обеспечивающих взаимодействие между объектом и пользователем этого объекта. Спецификации CTS не ограничивают число интерфейсов, реализуемых в рамках класса |
Абстрактность или конкретность | Абстрактные классы не позволяют непосредственное сознание их экземпляров – они предназначены для определения общих элементов поведения производных типов. Конкретные классы могут быть созданы непосредственно |
Видимость | Каждый класс должен иметь атрибут видимости (visibility). По сути, этот атрибут указывает, доступен данный класс для использования внешними компоновочными блоками или он доступен для использования только внутри определяющего этот класс компоновочного блока (как, например, приватный класс справки) |
Тип структуры
Понятие структуры в CTS также формализовано. Если вы знаете C, вам будет приятно узнать, что эти пользовательские типы "выжили" и в мире .NET (хотя внутренне они ведут себя немного по-иному). Упрощенно говоря, структура - это "облегченный" тип класса с семантикой на базе значений. Более подробная информация о структурах предлагается в главе 3. Обычно структуры лучше всего подходят для моделирования геометрических и математических данных, и в C# для создания структур используется ключевое слово struct.
// Тип структуры C#.
struct Point {
// Структуры могут содержать поля.
public int xPos, yPos;
// Структуры могут содержать параметризованные конструкторы.
public Point (int x, int у) {xPos = x; yPos = y;}
// Структуры могут определять методы.
public void Display() {
Console.WriteLine("({0}, {1})", xPos, yPos);
}
}
Тип интерфейса
Интерфейс - это именованная коллекция определений абстрактных членов, которая может поддерживаться (т.е. реализоваться) данным классом или структурой. В отличие от модели COM, интерфейсы .NET не являются производными одного общего базового интерфейса, такого как IUnknown. В C# типы интерфейса определяются с помощью ключевого слова interface, например:
// Тип интерфейса C#.
public interface IDraw {
void Draw ();
}
Сами по себе интерфейсы не очень полезны. Однако, когда класс или структура реализуют данный интерфейс своим собственным уникальным образом, вы можете запросить доступ к соответствующим функциональным возможностям, используя ссылку на интерфейс в полиморфной форме. Программирование на базе интерфейсов будет рассматриваться в главе 7.
Тип перечня
Перечень - это удобная программная конструкция, в которой группируются пары "имя-значение". Предположим, вы создаете видеоигру, в которой игроку позволяется выбрать персонажа в одной из трех категорий: Wizard (маг), Fighter (воин) или Thief (мошенник). Вместо того чтобы использовать и отслеживать числовые значения, соответствующие каждой из возможностей, вы можете построить перечень, используя для этого ключевое слово enum.
// Тип перечня C#.
public enum CharacterType {
Wizard = 100,
Fighter = 200,
Thief = 300
}
По умолчанию для каждого элемента выделяется блок памяти, соответствующий 32-битовому целому, но при необходимости это значение можно изменить (например, в случае программирования для устройств с малыми объемами памяти, таких как КПК). Спецификации CTS предполагают, что типы перечня должны "получаться" из общего базового класса, System.Enum. Из главы 3 вы узнаете, что этот базовый класс определяет ряд весьма полезных членов, которые позволяют программно извлекать, обрабатывать и преобразовывать соответствующие пары "имя-значение".
Тип делегата
Делегат - это .NET-эквивалент обеспечивающих типовую безопасность указателей функций C. Главное отличие заключается в том, что делегат .NET- это класс, получаемый путем наследования System.MulticastDelegate, а не просто указатель на конкретный адрес в памяти. В C# делегаты объявляются с помощью ключевого слова delegate.
// Этот тип делегата C# может 'указывать' на любой метод, возвращающий
// целое значение и получающий на вход два целых значения.
public delegate int BinaryOp(int x, int y);
Делегаты полезны, когда требуется обеспечить элементу возможность передачи вызова другому элементу, что создает основу для архитектуры обработки событий .NET. В главах 8 и 14 будет показано, что делегаты имеют внутреннюю поддержку методов многоадресного (предназначенного для множества получателей) и асинхронного вызова.
Члены типов
Теперь после рассмотрения всех типов, имеющих формальное определение в CTS, вы должны осознать, что большинство типов может иметь любое число членов. Формально член типа - это любой элемент множества {конструктор, деструктор (finalizer), статический конструктор, вложенный тип, операция, метод, свойство, индексатор, поле, поле только для чтения, константа, событие}.
Спецификации CTS определяют различные "характеристики", которые могут связываться с данным членом. Например, каждый член имеет признак, характеризующий его доступность (открытый, частный, защищенный и т.д.). Некоторые члены могут объявляться как абстрактные, чтобы навязать полиморфное поведение производным типам, или виртуальные, чтобы определить фиксированную (но допускающую замену) реализацию. Большинство членов может обозначаться как статические ("привязанные" к уровню класса) или как члены экземпляра ("привязанные" к уровню объекта). Конструкция членов типа будет подробно обсуждаться в следующих главах.
Замечание. Как будет показано в главе 10, в .NET 2.0 поддерживается конструкция обобщенных типов и обобщенных членов.
Встроенные типы данных CTS
Еще одной особенностью CTS, о которой следует знать, является то, что спецификации CTS определяют четкий набор базовых типов данных. Хотя каждый язык обычно предлагает свое уникальное ключевое слово, используемое для объявления конкретного встроенного типа данных CTS, все эти ключевые слова в конечном счете приводят к соответствующему типу, определенному в компоновочном блоке mscorlib.dll. Взгляните на табл. 1.3, предлагающую информацию о том, как базовые типы данных CTS выражены в разных языках .NET.
Таблица 1.3. Встроенные типы данных CTS
Тип данных CTS | Ключевое слово VB .NET | Ключевое слово C# | Ключевое слово Managed Extensions for C++ |
System.ByteByte | Byte | byte | unsigned char |
System.SByteSByte | SByte | sbyte | signed char |
System.Int16 | Short | short | short |
System.Int32 | Integer | int | int или long |
System.Int64 | Long | long | __int64 |
System.UInt16 | UShort | ushort | unsigned short |
System.UInt32 | UInteger | uint | unsigned int или unsigned long |
System.UInt64 | ULong | ulong | unsigned __int64 |
System.SingleSingle | Single | float | Float |
System.DoubleDouble | Double | double | Double |
System.ObjectObject | Object | object | Object^ |
System.CharChar | Char | char | wchar_t |
System.StringString | String | String | String^ |
System.DecimalDecimal | Decimal | decimal | Decimal |
System.BooleanBoolean | Boolean | bool | Bool |
Общеязыковые спецификации
Вы, конечно, знаете, что разные языки программирования выражают одни и те же программные конструкции в своих уникальных терминах. Например, в C# конкатенация строк обозначается знаком "плюс" (+), a в VB .NET для этого используется амперсанд (&). Даже тогда, когда два языка выражают одну и ту же программную идиому (например, функцию, не возвращающую никакого значения), весьма вероятно то, что при этом используется разный синтаксис.
' Не возвращающий ничего метод VB.NET.
Public Sub MyMethod()
' Некоторый программный код…
End Sub
// Не возвращающий ничего метод C#.
public void MyMethod() {
// Некоторый программный код…
}
Вы уже видели, что эти небольшие отличия в синтаксисе несущественны с точки зрения среды выполнения .NET, поскольку соответствующие компиляторы (в данном случае это vbc.exe и csc.exe) генерируют аналогичные множества CIL-инструкций. Но языки могут также отличаться по функциональности. Конкретный язык .NET может, например, иметь ключевое слово или не иметь его для представления данных без знака, может поддерживать или не поддерживать типы указателя. С учетом таких вариаций возможностей необходимо иметь базовый уровень, которому соответствовали бы все языки с поддержкой .NET.
Спецификации CLS (Common Language Specification – общеязыковые спецификации)- это набор правил, которые во всех подробностях описывают минимальное и полное множество возможностей, которые должен поддерживать данный .NET-компилятор, чтобы генерировать программный код, подходящий для CLR, и в то же время быть одинаково доступным для всех языков, предназначенных для платформы .NET. Во многих отношениях CLS можно рассматривать, как подмножество полного набора функциональных возможностей, определенного в рамках CTS.
Спецификации CLS являются в конечном счете набором правил, которых должны придерживаться создатели компилятора, если они собираются создать продукт, который во "вселенной" .NET функционирует "незаметно" для пользователя. Каждое правило имеет простое имя (например, "Правило CLS номер 6") и описывает, какое отношение это правило имеет к тем, кто создает компиляторы, и тем, кто каким-то образом взаимодействует с ними. Квинтэссенцией CLS является могущественное правило 1.
• Правило 1. Правила CLS применяются только к тем компонентам типа, которые открыты для доступа за пределами определяющего их компоновочного блока.
С учетом этого правила вы можете сделать (правильное) заключение, что все остальные правила CLS не касаются логики, используемой для внутреннего устройства типа .NET. Единственные аспекты типа, которые должны согласовываться с CLS, – это определения членов (т.е. соглашения о выборе имен, параметры и возвращаемые типы). Логика реализации конкретного члена может использовать любые несогласованные с CLS технологии, если только это будет скрыто от "внешнего мира".
Так, следующий метод Add() не является согласованным с правилами CLS, поскольку для параметров и возвращаемых значений используются данные без знака, которые в CLS не указаны.
public class Calc {
// Эти открытые данные без знака не согласуются с CLS!
public ulong Add( ulong x, ulong у) { return x + у; }
}
Но если вы используете данные без знака только внутри типа, как указано ниже
public class Calc {
public int Add(int x, int y) {
// Здесь переменная ulong используется только внутри типа,
// поэтому правила CLS не нарушается.
ulong temp;
...
return x + у;
}
}
то правила CLS остаются выполненными, и вы можете быть уверены, что теперь любой язык .NET сможет вызвать метод Add().
Конечно, кроме правила 1 в CLS определено много других правил. Например, в CLS описывается, как язык должен представлять строки текста, перечни, статические члены и т.д. К счастью, совсем не обязательно запоминать все эти правила, чтобы стать искусным разработчиком .NET. Снова повторим, что глубокое и полное понимание спецификаций CTS и CLS необходимо только создателям соответствующих инструментов разработки и компиляторов.
Гарантия CLS-совместимости
Как вы узнаете из текста этой книги, в C# имеется ряд программных конструкций, которые яе являются CLS-совместимыми. Однако хорошим известием является то, что вы можете заставить компилятор C# выполнять проверку вашего программного кода на соответствие CLS, используя дли этого один атрибут .NET.
// Указание компилятору C# выполнить проверку на соответствие CLS.
[assembly: System.CLSCompliant(true)]
В главе 12 будут рассмотрены тонкости программирования на основе использования атрибутов, Пока что важно просто понять, что атрибут [CLSCompliant] дает компилятору C# указание проверять каждую строку программного кода на соответствие правилам CLS. Если обнаружится нарушение правил CLS, вы получите сообщение об ошибке компиляции и описание некорректного программного кода.
Общеязыковая среда выполнения
В дополнение к спецификациям CTS и CLS, последней на данный момент аббревиатурой, которую мы рассмотрим, будет аббревиатура CLR (Common Language Runtime – общеязыковая среда выполнения). Для программирования термин среда, выполнения можно понимать, как набор внешних сервисов, необходимых для выполнения данной скомпилированной единицы программного кода. Например» когда разработчик при создании нового приложения использует библиотеку базовых классов Microsoft (MFC), он знает, что для выполнения его программы потребуется соответствующий выполняемый модуль библиотеки MFC (т.е. mfc42.dll). Другие популярные языки также предлагают соответствующие выполняемые модули. Программисты VB6 привязаны к одному или двум выполняемым модулям (например, msvbvm60.dll). Разработчики Java привязаны к виртуальной машине Java (JVM) и т.д.
Платформа .NET предлагает совсем другой принцип организации среды выполнения. Разница между средой выполнения .NET и средой выполнения, о которой говорилось выше, заключается в том, что среда выполнения .NET обеспечивает единый и вполне определенный "слой" выполнения, общий для всех языков и платформ, совместимых с .NET.
Основной механизм CLR физически заключается в библиотеке, называемой mscoree.dll (известной также под названием Common Object Runtime Execution Engine – общий объектный модуль механизма выполнения). Когда на компоновочный блок ссылаются для использования, mscoree.dll автоматически загружается и, в свою очередь, загружает в память требуемый компоновочный блок. Механизм выполнения отвечает за целый ряд задач. Прежде всего, и это самое главное, за выяснение расположения компоновочного блока и нахождение запрашиваемого типа в бинарном объекте с помощью чтения содержащихся там метаданных. Затем среда CLR размещает тип в памяти, преобразует CIL-код в соответствующие платформе инструкции, выполняет все необходимые проверки безопасности, а затем выполняет полученный программный код.
Вдобавок к загрузке созданных вами компоновочных блоков и созданию пользовательских типов, CLR также, если это необходимо, взаимодействует с типами, содержащимися в библиотеках базовых классов .NET. Хотя вся библиотека базовых классов разбита на целый ряд отдельных компоновочных блоков, "ключевым" компоновочным блоком является mscorlib.dll. Файл mscorlib.dll содержит множество базовых типов, которые объединяют в себе решения широкого спектра общих задач программирования, а также базовые типы данных, используемые всеми языками .NET. При построении .NET-приложений вы автоматически получаете доступ к этому специальному компоновочному блоку.
На рис. 1.3 показана система связей, возникающих между вашим исходным кодом (использующим типы из библиотеки базовых классов), .NET-компилятором и механизмом выполнения .NET.
Различия между компоновочными блоками, пространствами имен и типами
Каждый из нас понимает важность библиотек программного кода. Цель библиотек, таких как MFC, J2EE или ATL, – дать разработчику готовый набор блоков уже существующего программного кода, опираясь на которые можно строить новые приложения. Но язык C# не предлагает библиотек с программным кодом для конкретного языка. Разработчики C# могут использовать .NET-библиотеки, нейтральные в языковом отношении. Для того чтобы все типы в библиотеках базовых классов были правильно организованы, платформа .NET предлагает использовать понятие пространства имен.
Упрощенно говоря, пространство имен является группой связанных типов, содержащихся в компоновочном блоке. Например, пространство имен System.IO содержит типы, связанные с операциями ввода-вывода, пространство имен System.Data определяет основные типы для работы с базами данных и т.д. Важно понимать, что один компоновочный блок (такой как, например, mscorlib.dll) может содержать любое число пространств имен, каждое из которых может, в свою очередь, содержать любое число типов.
Чтобы ситуация стала более ясной, взгляните на рис. 1.4, на котором показан снимок окна Object Browser из Visual Studio 2005. Этот инструмент позволяет видеть компоновочные блоки, на которые ссылается текущий проект, пространства имен, содержащиеся в компоновочных блоках, типы, существующие в пределах данного пространства имен, и члены каждого типа.
Обратите внимание на то, что mscorlib.dll содержит очень много самых разных пространств имея, и в каждом из этих пространств имен содержатся свои семантически связанные типы.
Рис. 1.3. Модуль mscoree.dll в действии
Основным отличием этого подхода от таких зависящих от конкретного языка библиотек, как MFC, является то, что в результате все языки, поддерживаемые в среде выполнения .NET используют одни и те же пространства имен и одни и те же типы.
Рис.1.4. Один компоновочный блок может содержать любое количество пространств имен
Для иллюстрации рассмотрим следующие три программы, представляющие вариации вездесущего примера "Hello World" соответственно на C#, VB .NET и Managed Extensions for C++.
// Hello world на языке C#
using System;
public class MyApp {
static void Main() {
Console.WriteLine("Привет из C#");
}
}
' Hello world на языке VB .NET
Imports System
Public Module MyApp
Sub Main()
Console.WriteLine("Привет из VB .NET")
End Sub
End Module
// Hello world на языке Managed Extensions for C++
#include "stdafx.h"
using namespace System;
int main(array‹System::String^› ^args) {
Console::WriteLine("Привет из managed C++");
return 0;
}
Заметим, что здесь в любом из языков используется класс Console, определенный в пространстве имен System. Если отбросить незначительные синтаксические вариации, то эти три приложения выглядят очень похожими, как по форме, так и по логике.
Очевидно, вашей главной целью, как разработчика .NET. является получение исчерпывающей информации обо всем разнообразии типов, определенных в рамках (многочисленных) пространств имен .NET. Главным из пространств имен, о которых следует знать, является System. Это пространство имен предлагает базовый набор типов, которые вы, как разработчик .NET. будете использовать снова и снова. Фактически вы не сможете построить ни одного реально работающего C#-приложеиия, не сославшись, как минимум, на пространство имен System. В табл. 3.4 предлагаются краткие описания некоторых (но, конечно же, не всех) пространств имен .NET.
Таблица 1.4. Пространства имен .NET
Пространства имен .NET | Описание |
System | В рамках System вы найдете множество полезных типов, связанных с внутренними данными, математическими вычислениями, переменными окружения, генерированием случайных чисел и сбором мусора, а также с обработкой типичных исключительных ситуаций и атрибутов |
System.Collections System.ColIections.Generiс | Эти пространства имен определяют ряд контейнерных объектов (ArrayList, Queue и т.д.), а также базовых типов и интерфейсов, которые позволяют строить пользовательские коллекции. В .NET 2.0 типы коллекций обладают дополнительными общими возможностями |
System.Data System.Data.Odbc System.Data.OracleClient System.Data.OleDb System.Data.SqlClient | Эти пространства имен используются для взаимодействия с базами данных на основе ADO.NET |
System.Diagnostics | Здесь вы найдете множество типов, которые могут использоваться для программной отладки и трассировки исходного кода |
System.Drawing System.Drawing.Drawing2D System.Drawing.Printing | Здесь вы найдете множество типов для работы с графическими примитивами, такими как растровые изображения, шрифты и пиктограммы, а также для вывода на печать |
System.IO System.IO.Compression System.IO.Ports | Эти пространства имен включают средства файлового ввода-вывода, буферизации и т.д. В .NET 2.0 пространства имен IO предлагают поддержку сжатия и работы с портами |
System.Net | Это пространство имен (как и другие родственные пространства имен) содержит типы, связанные с сетевым программированием (запросы/ответы, сокеты, конечные точки соединений и т.д.) |
System.Reflection System.Reflection.Emit | Эти пространства имен определяют типы, связанные с обнаружением типов в среде выполнения и динамическим созданием типов |
System.Runtime.InteropServices | Это пространство имен обеспечивает средства взаимодействия типов .NET с "неуправляемым программным кодом" (это, например, DLL на базе C и COM-серверы) |
System.Runtime.Remoting | Это пространство имен (среди прочих) определяет типы, используемые для построения решений на основе возможностей слоя удаленного доступа .NET |
System.Security | Безопасность – это неотъемлемый аспект платформы .NET. В пространствах имен, объединенных идеей безопасности, вы найдете множество типов, связанных с разрешением доступа, криптографической защитой и т.д. |
System.Threading | Это пространство имен определяет типы, используемые при построении многопоточных приложений |
System.Web | Ряд пространств имен, специально предназначенных для разработки Web-приложений .NET, включая Web-сервисы ASP.NET и XML |
System.Windows.Forms | Это пространство имен содержит типы, которые упрощают процесс создания традиционных GUI-приложений (приложений с графическим интерфейсом) для настольных систем |
System.Xml | Связанные с XML пространства имен, содержащие множество типов, используемых для взаимодействия с XML-данными |
Программный доступ к пространствам имен
Не помешает повторить снова, что пространство имен является ничем иным, как подходящим для человека способом логически понять и организовать связанные типы. Снова рассмотрим пространство имен System. Можно считать, что System.Console представляет класс, названный Console и содержащийся в пространстве имен System. Но для среды выполнения .NET это не так. Механизм среды выполнения видит только отдельную единицу, названную System.Console.
В C# ключевое слово using упрощает ссылки на типы, определенные в данном пространстве имен. Вот как оно используется. Допустим, вы строите традиционное приложение для настольной системы. В главном окне должна отображаться некоторая диаграмма, основанная на информации, полученной от внутренней базы данных, и логотип компании. Конечно, для изучения типов в пространствах имен требуется время, но вот несколько очевидных "кандидатов", подходящих для ссылок в описанной выше программе.
// Пространства имен, необходимые для данного приложения.
using System; // Общие типы базовых классов,
using System.Drawing; // визуализация графики,
using System.Windows.Forms; // GDI-элементы,
using System.Data; // общий доступ к данным,
using System.Data.SqlClient; // доступ к данным MS SQL Server.
Выбрав некоторое число пространств имен (и указав ссылки на компоновочные блоки, которые их определяют), вы получаете возможность создавать экземпляры соответствующих типов. Например, если вы хотите создать экземпляр класса Bitmap (из пространства имен System.Drawing), вы можете использовать следующий программный коя,
// Явный список пространств имен, используемых в данном файле.
using System;
using System.Drawing;
class MyApp {
public void DisplayLogo() {
// Создание изображения 20x20.
Bitmap companyLogo = new Bitmap(20, 20);
...
}
}
Поскольку ваше приложение ссылается на System.Drawing, компилятор сможет выяснить, что класс Bitmap является членом указанного пространства имен. Если бы вы не указали здесь пространство имен System.Drawing, то получили бы ошибку компиляций. Но для определения переменных можно также использовать полностью определённое, или абсолютное имя.
// Здесь System.Drawing не указывается!
Using System;
class MyApp {
public void DisplayLogo() {
// Использование абсолютного имени
System.Drawing.Bitmap companyLogo = new System.Drawing.Bitmap(20, 20);
…
}
}
Использование абсолютных имен для определения типа, конечно, упрощает понимание программного кода, но я думаю, и вы не станете возражать, что ключевое слово C# using уменьшает объем необходимого ввода. В этом тексте мы будем избегать использования абсолютных имен (за исключением тех случаев, когда из-за этого возникает явная неоднозначность), отдавая предпочтение использованию ключевого слова using.
При этом следует понимать, что использование using является лишь альтернативой использования абсолютных имен, поскольку в программном коде CIL всегда используются абсолютные имена, так что оба указанных подхода дают совершенно одинаковые результаты в CIL и с точки зрения производительности, и с точки зрения размера компоновочного блока.
Ссылки на внешние компоновочные блоки
Вдобавок к указанию пространства имен с помощью ключевого слова C# using, необходимо указать компилятору C# имя компоновочного блока, содержащего реальное CIL-определение соответствующего типа. Выше уже упоминалось, что многие базовые пространства имен .NET содержатся в mscorlib.dll. Однако тип System.Drawing.Bitmap содержится в другом компоновочном блоке с именем System.Drawing.dll. Большинство компоновочных блоков .NET Framework размещается в специальном каталоге, называемом GAC (Global Assembly Cache - глобальный кэш компоновочных блоков). На машинах Windows это может быть каталог %windir%\Assembly, как показано на рис. 1.5.
Рис. 1.5. Библиотеки базовых классов в GAC
В зависимости от используемого инструмента разработки приложений .NET может быть несколько разных способов информирования компилятора о том, какие компоновочные блоки следует включить в цикл компиляции. Подробно это будет обсуждаться в следующей главе.
Использование ildasm.exe
Если вас пугает перспектива освоения всех пространств имен платформы .NET, вспомните о том, что уникальность любого пространства имен заключается в том, что оно содержит типы, некоторым образом семантически связанные между собой. Поэтому, например, если вам не нужен интерфейс пользователя для простого консольного приложения, то смело можете забыть (среди прочих) о пространствах имен System.Windows.Forms и System.Web. Если вы строите приложение для работы с изображениями, то вам вряд ли понадобятся пространства имен для работы с базами данных. К тому же, как в случае любой новой библиотеки готового программного кода, вы можете учиться по ходу дела.
Утилита ildasm.exe (Intermediate Language Disassembler utility – утилита дизассемблера промежуточного языка) позволяет загрузить любой компоновочный блок .NET и исследовать его содержимое, включая соответствующий манифест, программный код CIL и метаданные типов.
По умолчанию файл ildasm.exe должен быть установлен в папку C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin (если вы не можете найти ildasm.exe в указанном месте, просто выполните поиск файла по ключу "ildasm.exe" на своей машине).
Обнаружив и запустив этот файл, а открывшемся окне выберите команду меню File→Open и перейдите к компоновочному блоку, который вы хотите исследовать. С целью иллюстрации здесь (рис. 1.6) показав компоновочный блок CSharpCalculator.exe, о котором уже шла речь выше. Утилита ildasm.exe представляет структуру компоновочного блока, используя всем знакомый формат дерева просмотра.
Рис. 1.6. Ваш новый лучший друг ildasm.exe
Просмотр CIL-кода
В дополнение к тому, что вы можете видеть пространства имен, типы и их члены в компоновочном блоке. Ildasm.exe дозволяет также просмотреть CIL-инструкции любого члена. Например, если выбрать двойным щелчком метод Main() класса CalcApp, то появится отдельное окно, в котором будет отображаться соответствующий CIL-код (рис. 1.7).
Рис. 1.7. Просмотр CIL-кода
Просмотр метаданных типов
Если вы захотите просмотреть метаданные типов для загруженного в настоящий момент компоновочного блока, просто нажмите ‹Ctrl+M›. На рис. 1.8 показаны метаданные для метода Calc.Add().
Рис. 1.8. Просмотр метаданных типов с помощью ildasm.exe
Просмотр метаданных компоновочных блоков
Наконец, если вы захотите просмотреть содержимое манифеста компоновочного блока, то вам нужно двойным щелчком открыть пиктограмму MANIFEST (рис. 1.9).
Рис. 1.9. Двойной щелчок на этой строке покажет манифест компоновочного блока
Не сомневайтесь в том, что ildasm.exe имеет не только те опции, о которых говорилось выше. Дополнительные возможности этого инструмента будут обсуждаться и дальше. По мере чтения материала книги я рекомендую вам просматривать ваши компоновочные блоки с помощью ildasm.exe, чтобы вы видели, как ваш программный код C# транслируется в независимый от платформы программный код CIL. Конечно, чтобы быть суперзвездой C#, совсем не обязательно быть экспертом по программному коду CIL, но понимание синтаксиса CIL только укрепит ваши "мускулы программирования".
Инсталляция среды выполнения .NET
Для вас не должно быть сюрпризом то, что компоновочные блоки .NET могут выполняться только на машине, на которой установлен каркас .NET Framework. Для вас, как для разработчика .NET-приложений, это не должно быть проблемой, поскольку ваша машина будет должным образом сконфигурирована уже в процессе установки свободно доступного пакета .NET Framework 2.0 SDK (или любой коммерческий среды разработки .NET-приложений, например Visual Studio 2005).
Однако, если вы развернете компоновочный блок на компьютере, который не имеет установленной системы .NET, этот компоновочный блок выполняться не сможет. По Этой причине Microsoft предлагает установочный пакет dotnetfx.exe, который может быть бесплатно получен и установлен вместе с вашим программным обеспечением. Эта установочная программа включена в .NET Framework 2.0 SDK, а также доступна для бесплатной загрузки с узла Microsoft.
После установки dotnetfx.exe ваша машина будет содержать библиотеки базовьх классов .NET, файлы среды выполнения .NET (mscoree.dll) и дополнительно инфраструктуру .NET (например, GAC).
Замечание. При построении Web-приложений .NET не предполагается, что на машине конечного пользователя будет установлен каркас .NET Framework, поскольку браузер конечного пользователи просто получает общий HTML-код и, возможно, JavaScript-код клиента.
Платформенная независимость .NET
В завершение этой ставы позвольте мне сказать несколько слов по поводу независимости платформы .NET. Неожиданностью для многих разработчиков является то, что компоновочные блоки .NET могут разрабатываться и выполняться в операционных системах, отличных от операционных систем Microsoft (Mac OS X, многочисленные вариации Linux, в частности BeOS и FreeBSD и др.). Чтобы поднять, почему это возможно, мы с вами должны рассмотреть еще одну аббревиатуру, используемую во "вселенной" .NET: это аббревиатура CLI (Common Language infrastructure – общеязыковая инфраструктура).
Когда Microsoft выпустила язык программирования C# и платформу .NET, она выпустила также множество формальных документов, которые описали синтаксис и семантику языков C# и CIL, формат компоновочного блока .NET, базовые пространства имен и работу гипотетического механизма среды выполнения .NET (известного также под названием VES, или Virtual Execution System – виртуальная система выполнения). Еще лучше то, что все эти документы представлены в организации Ecma International (http://www.ecma-internatiоnal.org) для утверждения их в качестве официальных международных стандартов. Интересующими нас спецификациями являются:
• ECMA-334: спецификации языка C#;
• ECMA-335: общеязыковая инфраструктура (CLI).
Важность этих документов проясняется, если заметить, что они предоставляют третьим сторонам возможность строить дистрибутивы платформы .NET для любого числа операционных систем и/или процессоров. Спецификации ECMA-335, наверное, более "содержательны", поэтому они разбиты на пять разделов, как показано в табл. 1.5.
Таблица 1.5. Разделы CLI
Разделы ECMA-335 | Описание |
Раздел I. Архитектура | Описывает общую архитектуру CLI, включая правила CTS и CLS, а также работу механизма среды выполнения .NET |
Раздел II. Метаданные | Описывает структуру метаданных .NET |
Раздел III. CIL | Описывает синтаксис и семантику CIL-кода |
Раздел IV. Библиотеки | Дает высокоуровневый обзор минимальных и полных библиотек классов, которые должны поддерживаться дистрибутивом .NET |
Раздел V. Дополнения | Коллекция "вспомогательных" элементов, таких гак рекомендации по проектированию библиотек классов и подробности реализации компилятора CIL |
Заметим, что в разделе IV (Библиотеки) определяется минимальное множество пространств имен, которые представляют только базовые сервисы, ожидаемые от CLI-дистрибутива (коллекции, консольный ввод-вывод, файловый ввод-вывод, поточная обработка, отображение, сетевой доступ, базовые средства защиты, XML-манипуляции и т.д.). Такой CLI-дистрибутив не определяет пространства имен, упрощающих разработку Web-приложений (ASP.NET), доступ к базам данных (ADO.NET) или построение графического интерфейса пользователя (Windows Forms).
Благоприятным, однако, является то, что главные дистрибутивы .NET распространяют библиотеки CLI с эквивалентами Microsoft для ASP.NET, ADO.NET и Windows Forms, чтобы обеспечить полноценные платформы разработки производственного уровня. На сегодняшний день есть две главные реализации CLI (кроме предложений Microsoft, предназначенных только для Windows). Хотя в этой книге рассматривается создание .NET-приложений с помощью .NET-дистрибутива Microsoft, в табл. 1.6 представлена также информация о проектах Mono и Portable.NET.
Как Mono, так и Portable.NET обеспечивают ECMA-совместимость компилятора C# и механизма выполнения .NET, примеры программного кода, документацию, а также многочисленные инструменты разработки приложений, которые по функциональности эквивалентны инструментам, входящим в состав .NET Framework 2.0 SDK от Microsoft. К тому же Mono и Portable.NET поставляются с компиляторами VB .NET, Java и C.
Замечание. Если вы хотите узнать больше о Mono или Portable.NET, прочитайте книгу М. J. Easton и Jason King, Cross-Platform .NET Development: Using Mono, Portable.NET, and Microsoft .NET (Apress, 2004).
Таблица 1.6. .NET-дистрибутивы с открытым исходным кодом
Дистрибутив | Описание |
http://www.mono-project.com | Проект Mono является дистрибутивом CLI с открытым исходным кодом, предназначенным для различных вариантов Linux (например, SuSE, Fedora и т.д.), а также дня Win32 и Mac OS X |
http://www.dotgnu.org | Portable.NET – это другой дистрибутив CLI с открытым исходным кодом, предназначенный для множества операционных систем. Portable.NET нацелен на то, чтобы обслуживать как можно больше операционных систем (Win32, AIX, BeOS, Mac OS X, Solaris, все главные варианты Linux и т.д.) |
Резюме
Целью этой главы было описание базовых концепций, необходимых для освоения остального материала этой книги. Сначала были рассмотрены ограничения и сложности технологий, появившихся до .NET, а затем был предложен обзор того, как .NET и C# пытаются упростить существующее положение вещей.
В сущности .NET можно свести к механизму среды выполнений (mscoree.dll) и библиотеке базовых классов (mscorlib.dll и сопутствующие файлы). Общеязыковая среда выполнения (CLR) способна принять любой бинарный .NET-объект (называемый компоновочным блоком), если только этот бинарный объект подчиняется правилам управляемого программного кода. Как вы убедились, компоновочные блоки содержат CIL-инcтрукций (в дополнение к метаданным типов и манифесту компоновочного блока), которые с помощью JIT-компилятора компилируются в специфические инструкции платформы. Кроме того., была выяснена роль общеязыковых спецификаций (CLS) и общей системы типов (CTS).
Затем была рассмотрена, утилита ildasm.exe, а также то, как с помощью dotnetfx.exe настроить машину для использования .NET-приложений. В заключение было сказано несколько слов о независимой от платформ природе C# и .NET.
ГЛАВА 2. Технология создания приложений на языке C#
Как разработчик программ на языке C#, вы имеете возможность выбрать любой из множества доступных инструментов разработки .NET-приложений. Целью этой главы является обзор самых разных инструментов разработки .NET, включая, конечно же Visual Studio 2005. Однако начнется глава с рассмотрения компилятора командной строки C#, csc.exe, для работы с которым будет достаточно самого простого текстового редактора., например программы Блокнот (noteepad.exe). Кроме того, мы с вами выясним, как выполнить отладку компоновочных блоков .NET с командной строки с помощью cordbg.exe. Освоив компиляцию и отладку компоновочных блоков без графического интерфейса, мы затем выясним, как можно редактировать и компилировать файлы исходного кода C# c помощью приложения TextPad.
Конечно, с текстом этой книги можно работать, используя только csc.exe и Блокнот/TextPad, но я думаю, вы заинтересованы в освоении более широких возможностей, предлагаемых в рамках современных IDE (Integrated Development Environment – интегрированная среда разработки). Поэтому мы рассмотрим также SharpDevelop – интегрированную среду разработки с открытым исходным текстом. По функциональности она конкурирует со многими коммерческими средствами разработки .NET, обладая тем дополнительным преимуществом, что она бесплатна, А после краткого обсуждения возможностей Visual C# 2005 Express мы приступим к рассмотрению Visual Studio 2005. Закончится глава небольшим обзором целого ряда дополнительных инструментов разработки .NET (многие из которых имеют открытый исходный код) и рекомендациями по поводу того, как эти инструменты получить.
Установка .NET Framework 2.0 SDK
Прежде чем начать строить .NET-приложения, используя язык программирования C# и каркас разработки приложений .NET Framework, сначала нужно установить свободно доступный пакет .NET Framework 2.0 SDK (Software Development Kit – комплект средств разработки программного обеспечения). Следует знать о том, что .NET Framework 2.0 SDK автоматически устанавливается при установке Visual Studio 2005 или Visual C# 2005 Express, поэтому если вы планируете установить одну из указанных систем, то загружать и отдельно устанавливать пакет программ .NET Framework 2.0 SDK нет необходимости.
Если у вас нет Visual Studio 2005 или Visual C# 2005 Express, то откройте страницу http://msdn.microsoft.com/netframework и выполните поиск по ключу ".NET Framework 2.0 SDK". Перейдя на соответствующую страницу, загрузите setup.exe и сохраните этот файл в подходящей папке на своем жестком диске. Затем двойным щелчком запустите этот выполняемый файл, чтобы установить соответствующее программное обеспечение.
После завершения установки на вашей машине появится не только необходимая инфраструктура .NET, но и множество инструментов разработки с очень хорошей справочной системой, примерами программного кода и обучающими программами, а также различные официальные документы с описанием системы.
По умолчанию пакет .NET Framework 2.0 SDK устанавливается в каталог C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0. Там вы найдете файл StartHere.htm. который (в полном соответствии с его названием) может служить в качестве отправной точки для доступа ко всем разделам документации. В табл. 2.1 предлагаются описания некоторых подкаталогов из корневого каталога инсталляции.
Таблица 2.1. Подкаталоги корневого каталога установки .NET Framework 2.0 SDK
Подкаталог | Описание |
\Bin | Содержит большинство инструментов разработки .NET-приложений. В файле StartTools.htm предлагаются описания всех утилит |
\Bootstrapper | Почти все содержимое этого каталога можно игнорировать, но следует знать, что именно здесь, в подкаталоге \Packages\DotNetFx, находится dotnetfx.exe (см. главу 1) |
\CompactFramework | Содержит программу установки .NET Compact Framework 2.0 |
\Samples | Содержит программу установки набора примеров .NET Framework 2.0 SDK. О том, как установить примеры, говорится в StartSamples.htm |
В дополнение к файлам, установленным в каталог C:\Program Files\ Microsoft Visual Studio 8\ SDK\v2.0, программа установки создает подкаталог Microsoft.NET\Framework в каталоге Windows. Там вы обнаружите отдельные подкаталоги для каждой версии .NET Framework, установленной на вашей машине. Внутри подкаталога, соответствующего конкретной версии, содержатся компиляторы командной строки для каждого языка, предлагаемого в рамках Microsoft .NET Framework (это CIL, C#, Visual Basic .NET, J# и JScript .NET), а также дополнительные утилиты командной строки и различные компоновочные блоки .NET.
Компилятор командной строки для C# (csc.exe)
Для компиляции исходного кода C# есть целый ряд возможностей. Не касаясь Visual Studio 2005 (и различных IDE сторонних производителей), здесь можно отметить компилятор командной строки для C#, csc.exe (где csc означает аббревиатуру для C-Sharp Compiler - компилятор C#), с помощью .NET которого можно создавать компоновочные блоки .NET. Указанный файл входит в комплект поставки .NET Framework 2.0 SDK. Вы, конечно же, не захотите создавать большие приложения с помощью компилятора командной строки, но знать, как компилировать *.cs-файлы вручную, вcе же важно. Можно указать несколько причин, по которым вы должны иметь представление о соответствующем процессе.
• Самым очевидным является то, что вы можете просто не иметь Visual Studio 2005.
• В ваших планах может быть использование автоматизированных средств разработки, таких как MSBuild или NAnt.
• Вы можете стремиться к расширению своего понимания C#. При использовании графических средств разработки приложений вы все равно даете инструкции csc.exe о том как обрабатывать исходные файлы C#. С этой точки зрения весьма полезно знать, что происходит "за кулисами".
Полезным "побочным эффектом" работы с csc.exe является то, что вам будет проще использовать другие инструменты командной строки, входящие в комплект поставки .NET Framework 2.0 SDK. В процессе изучения материала этой книги вы увидите, что многие очень важные утилиты оказываются доступны только из командной строки.
Настройка компилятора командной строки для C#
Чтобы использовать компилятор командной строки для C#, нужно, чтобы ваша система могла найти файл csc.exe. Если машина сконфигурирована неправильно, то при компиляции файлов C# вам придется указать полный путь к файлу csc.exe.
Чтобы система могла компилировать файлы *.cs из любого каталога, выполните следующие шаги (они соответствуют установке в Windows XP; в Windows NT/2000 эти шаги, будут аналогичными).
1. Щелкните на пиктограмме Мой Компьютер и выберите пункт Свойства из раскрывшегося контекстного меню.
2. Выберите вкладку Дополнительно и щелкните на кнопке Переменные среды.
3. Двойным щелчком на имени переменной Path в окне Системные переменные откройте окно ее изменения.
4. Добавьте в конец текущего значения Path следующую строку (не забудьте о том, что значения в списке переменной Path разделяются точкой с запятой)
C:\Windows\Microsoft.NET\Framework\v2.0.50215
Ваша строка должна соответствовать версии и месту размещения .NET Framework 2.0 SDK в вашей системе (проверьие павильность указанной вами строки в окне программы Проводник). Обновив переменную Path, можно проверить результат. Для этого следует закрыть все командные окна (чтобы изменения были приняты системой), а затем, открыв новое командное окно, ввести в нём
csc /?
Если все было сделано правильно, вы должны увидеть список опций настройки, поддерживаемых компилятором C#.
Замечание. В списке аргументов командной строки для любого средства разработки .NET в качестве разделителя можно использовать – или / (например, csc -? или csc /?).
Дополнительные средства командной строки .NET
До начала использования csc.exe добавьте в системную переменную Path следующее значение (снова не забудьте проверить правильность указанного пути).
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin
Напомним, что этот каталог содержит инструменты командной строки, которые используются в процессе разработки .NET-приложений. После создания двух указанных путей поиска у вас должна появиться возможность выполнять любую утилиту .NET из любого командного окна. Чтобы проверить правильность внесенных изменений, закройте все открытые командные окна, затем откройте новое командное окно и введите в нем следующую команду, позволяющую просмотреть опций утилиты GAC, gacutil.exe.
gacutil /?
Совет. Теперь вы знаете, как вручную настроить свою машину, но есть и более короткий путь. Среда .NET Framework 2.0 SDK предлагает уже сконфигурированное командное окно, распознающее все утилиты командной строки .NET. Используя кнопку Пуск, выберите из меню Все Программы→Microsoft .NET Framework SDK v2.0 и активизируйте строку SDK Command Prompt (Командная строка SDK).
Компоновка C#-приложений с помощью csc.exe
Теперь, когда машина распознает csc.exe, с помощью компилятора командной строки C# и программы Блокнот мы построим простой одномодульный компоновочный блок, который назовем TestApp.exe. Для начала нам нужен исходный код. Откройте программу Блокнот и введите в ее окно следующее.
// Простое приложение на языке C#.
using System;
class TestApp {
public static void Main() {
Console.WriteLine("Проверка! 1, 2, 3");
}
}
Завершив ввод, сохраните файл с именем TestApp.cs в подходящем месте на диске (например, в каталоге C:\CscExample). Теперь рассмотрим основные опции компилятора C#. Прежде всего нужно понять, как указывается имя и тип создаваемого компоновочного блока (это может быть, например, консольное приложение с именем MyShell.exe, библиотека программного кода с именем MathLib.dll, приложение Windows Forms с именем MyWinApp.exe и т.д.). Каждая из возможностей обозначается соответствующим флагом, передаваемым в сsc.exe в виде опции командной строки (табл. 2.2).
Таблица 2.2. Опции компилятора C#, указывающие выходные параметры
Опция | Описание |
/out | Используется для указания имени создаваемого компоновочного блока. По умолчанию имя компоновочного блока совпадает с именем исходного файла *.cs (в случае *.dll) или с именем типа, содержащего метод Main() программы (в случае *.exe) |
/target:exe | Используется для создания консольного приложения. Данный тип выходного файла подразумевается по умолчанию, поэтому эту опцию при построении консольного приложения можно опустить |
/target:library | Используется для построения одномодульного компоновочного блока *.dll |
/target:module | Используется для построения модуля. Модули являются составляющими многомодульных компоновочных блоков (см. главу 11) |
/target:winexe | Приложения Windows можно строить и с помощью флага /target:exe, но флаг /target:winexe исключает появление окна консоли в фоновом режиме |
Чтобы скомпилировать TestАрр.сs в консольное приложение с именем TestApp.exe, перейдите в каталог, содержащий файл с исходным кодом, и введите следующую строку команд (обратите внимание на то, что флаги командной строки должны быть указаны до имен входных файлов, а не после).
csc /target:exe TestApp.cs
Здесь не указан явно флаг /out, поэтому выполняемый файл будет назван TestApp.exе, поскольку класс определяющий точку входа программы (метод Main()), у нас называется TestApp. Следует знать о том, что почти все флаги компилятора C# имеют сокращенные версии написания. Например, можно использовать /t вместо /target (все сокращения можно увидеть с помощью ввода csс /? в командной строке).
csc /t:exe TestApp.cs
К тому же, поскольку флаг /t:exe определяет вывод, используемый компилятором C# по умолчанию, для компиляции TestApp.cs можно использовать следующую простую строку.
csc TestApp.cs
Рис. 2.1. Приложение TestApp в действии
Ссылки на внешний компоновочный блок
Теперь выясним, как компилировать приложение, использующее типы, определенные в отдельном компоновочном блоке .NET. Здесь, чтобы было ясно, почему при построении указанного выше приложения компилятор C# понял ссылку на тип System.Console, следует вспомнить о том (см. главу 1), что ссылка на mscorlib.dll при компиляции предполагается автоматически. Если же по какой-то особой причине эту ссылку необходимо отключить, следует использовать флаг /nostdlib.
Чтобы иллюстрировать механизм ссылки на внешние компоновочные блоки, мы модифицируем приложение TestApp так, чтобы оно отображало окно сообщения Windows Forms. Откройте файл TestApp.cs и измените его следующим образом.
using System;
// Добавьте это:
using System.Windows.Forms;
class TestApp {
public static void Main() {
Console.WriteLine("Проверка! 1, 2, 3");
// Добавьте это:
MessageBox.Show("Привет…");
}
}
Здесь с помощью ключевого слова using C# (см. главу 1) добавлена ссылка на пространство имен System.Windows.Forms. Напомним, что при явном указании пространств имен, используемых в рамках файла *.cs, нет необходимости использовать абсолютные имена (рукам легче).
В командной строке компилятору csc.exe следует сообщить о том. в каком из компоновочных блоков содержатся "используемые" пространства имен. Так, при использовании класса MessageBox с помощью опции /reference (которую можно "сократить" до /r) следует указать компоновочный блок System.Windows.Forrns.dll.
сsc /r:System.Windows.Forms.dll testapp.cs
Если теперь снова выполнить наше приложение, то вдобавок к выводу на консоль вы должны увидеть окно, подобное показанному на рис. 2.2.
Рис. 2.2. Ваше первое приложение Windows Forms
Компиляция множества файлов
В данном варианте приложение TestApp.exe использует один файл исходного кода *.cs. Вполне возможно, чтобы все типы .NET-приложения были представлены в одном файле *.cs, но большинство проектов компонуется из множества файлов *.cs, чтобы программный код был более гибким. Создайте новый класс и поместите его в отдельный файл HelloMsg.cs.
// Класс HelloMessage
using System;
using System.Windows.Forms;
class HelloMessage {
public void Speak() {
MessageBox.Show("Привет…");
}
}
Теперь обновите исходный класс ТestApp так, чтобы в нем использовался этот новый тип, а предыдущую логику Windows Forms закомментируйте.
using System;
// Это больше не требуется:
// using System.Windows.Forms;
class TestApp {
public static void Main() {
Console.WriteLine("Проверка! 1, 2, 3");
// И это тоже:
// MessageBox.Show("Привет…");
// Использование класса HelloMessage:
HelloMessage h = new HelloMessage();
h.Speak();
}
}
Скомпилируйте эти файлы C# с помощью их явного указания в качестве входных файлов.
csc /r:System.Windows.Forms.dll testapp.cs helloimsg.cs
В качестве альтернативы компилятор C# позволяет использовать групповой символ (*), информирующий csc.exe о том, что следует включить в текущий проект все файлы *.cs, содержащиеся в папке проекта:
css /r:System.Windows.Forms.dll *.cs
Результат выполнения новой программы не будет отличаться от предыдущего. Единственным отличием этих двух приложений будет только то, что теперь исходный код разделен на два файла.
Ссылки на множество внешних компоновочных блоков
В связи с рассматриваемой темой возникает следующий вопрос: "Что делать, если при использовании csc.exe нужно сослаться на множество внешних компоновочных блоков?" Просто перечислить все компоновочные блоки, используя в качестве разделителя точку с запятой. Для рассмотренного выше примера не требовалось указывать множество внешних компоновочных блоков, но вот соответствующий пример.
csc /r:System.Windows.Forms.dll;System.Drawing.dll *.cs
Работа с ответными файлами csc.exe
Очевидно, что при создании сложных C#-приложений из командной строки было бы очень неудобно набирать вручную все флаги и ссылки, необходимые для указания множества компоновочных блоков и входных файлов *.cs. Чтобы уменьшить объемы ручного ввода, компилятор C# допускает использование ответных файлов.
Ответные файлы C# содержат инструкции, которые будут использоваться компилятором в процессе компиляции входного потока. По соглашению это файлы с расширением *.rsp (сокращение от response – ответ). Предположим, что вы создали ответный файл TestApp.rsp, содержащий следующие аргументы (как видите, комментарии в данном случае обозначаются символом #).
# Это ответный файл для TestApp.exe из главы 2.
# Ссылки на внешние компоновочные блоки:
/r:System.Windows.Forms.dll
# опции вывода и файлы для компиляции
# (здесь используется групповой символ):
/target:exe /out:TestApp.exe *.cs
Предполагая, что этот файл сохранен в каталоге с компилируемыми файлами исходного кода C#, мы можем построить наше приложение с помощью команды, показанной ниже (обратите внимание на использование символа @).
csc @TestApp.rsp
При необходимости можно указать несколько входных файлов *.rsp (скажем, csc @FirstFile.rsp @SecondFile.rsp @ThirdFile.rsp). При таком подходе следует учитывать то, что компилятор обрабатывает командные опции в порядке их поступления. Поэтому аргументы командной строки в последнем файле *.rsp могут "переопределить" опции предыдущих ответных файлов.
Учтите и то, что флаги, указанные явно в командной строке до ответного файла, будут "переопределены" теми флагами, которые будут указаны в соответствующем файле *.rsp. Так, если вы введете
сsc /out:MyCoolApp.exe @TestApp.rsp
то именем компоновочного блока все равно будет TestApp.exe (а не MyCoolApp.exe), поскольку в ответном файле TestApp.rsp указан флаг /out:TestApp.ехe. Но если указать флаг после ответного файла, то уже флаг отменит опции ответного файла. Так, в результате выполнения следующей команды компоновочный блок получит имя MyCoolApp.exe.
csc @TestApp.rsp /out:MyCoolApp.exe
Замечание. Флаг /reference является кумулятивным. Независимо от того, где вы укажете внешние компоновочные блоки (до, после или внутри ответного файла), результатом будет объединение всех ссылок.
Ответный файл, используемый по умолчанию (csc.rsp)
В отношении ответных файлов следует знать то, что компилятор C# имеет ответный файл, используемый по умолчанию. Это файл csc.rsp, размещенный в том же каталоге, что и csc.exe (соответствующим каталогом может быть, например, C:\Windows\Microsoft.NET\Framework\v2.0.50215). Если открыть файл csc.rsp с помощью программы Блокнот, вы увидите, что в нем c помощью флага /r: уже указан целый набор компоновочных блоков .NET.
При компоновке C#-программы с помощью csc.ехe ссылка на этот фaйл выполняется автоматически, даже когда вы указываете свой файл *.rsp. С учетом ответного файла, используемого по умолчанию, наше приложение TestApp.exe будет успешно скомпилировано и при использовании следующей команды (так как в csc.rsp есть сcылка на System.Windows.Forms.dll).
csc /out:TestApp.exe *.cs
Если нужно отключить автоматическое чтение файла csc.rsp, следует указать опцию /noconfig.
csc @TestApp.rsр /noconfig
Компилятор командной строки C# имеет множество других опций, которые можно использовать для управления процессом генерирования компоновочных блоков .NET. Если вам требуется более подробная информация о функциональных возможностях csc.exe, прочитайте мою статью "Working with the C# 2.0 Command line Compiler" (Работа с компилятором командной строки C# 2.0), которую можно найти на страницах .
Отладчик командной строки (cordbg.exe)
Прежде чем перейти к рассмотрению возможностей компоновки C#-приложе-ний с помощью TextPad, следует отметить, что .NET Framework 2.0 SDK предлагает отладчик командной строки cordbg.ехe. Этот инструмент имеет множество опций, которые позволяют выполнить отладку компоновочного блока. Чтобы увидеть список этих опций, используйте флаг /?.
cordbg /?
В табл. 2.3 показаны некоторые (но, конечно же, не все) флаги с указанием их сокращенных форм, распознаваемые отладчиком cordbg.exe в сеансе отладки.
Таблица 2.3. Некоторые флаги командной строки отладчика cordbg.exe
Флаг | Описание |
b[reak] | Установить или показать текущие точки останова |
del[ete] | Удалить одну или несколько точек останова |
ex[it] | Выход из отладчика |
g[o] | Продолжить отладку текущего процесса до следующей точки останова |
o[ut] | Выйти из текущей функции |
p[rint] | Напечатать все загруженные переменные (локальные, аргументы и т.д.) |
si | Войти в следующую строку |
so | Перейти через следующую строку |
Большинство из вас предпочтет использовать интегрированный отладчик Visual Studio 2005, поэтому я не собираюсь комментировать все флаги cordbg.exe. Но для тех, кому это интересно, в следующем разделе предлагается краткое пошаговое описание основных этапов процесса отладки с использованием командной строки.
Отладка с командной строки
Перед началом отладки приложения с помощью cordbg.exe следует сгенерировать отладочные символы для текущего приложения, указав для csc.exe флаг /debug. Например, чтобы сгенерировать данные отладки для приложения TestApp.exe, введите следующую команду.
csc @testapp.rsp /debug
В результате генерируется новый файл, в данном случае с именем testapp.pdb. Без соответствующего файла *.pdb использовать cordbg.exe тоже можно, но при этом в процессе отладки вы не сможете видеть исходный код C# (что, как правило, важно, если вы не хотите усложнять себе жизнь чтением программного кода CIL).
Сгенерировав файл *.pdb, откройте сеанс отладки, указав для cordbg.exe свой компоновочный блок .NET в виде аргумента командной строки (при этом файл *.pdb будет загружен автоматически).
cordbg.exe testapp.exe
Начнется режим отладки, и вы получите возможность применять любые допустимые флаги cordbg.exe в командной строке (cordbg) (рис. 2.3).
Чтобы выйти из режима отладки cordbg.exe, следует просто ввести exit (или, сокращенно, ех). Если вы не являетесь стойким приверженцем использования командной строки, вы предпочтете использовать возможности графического отладчика, предлагаемого интегрированной средой разработки. В любом случае для получения дополнительной информации обратитесь к разделу в документации .NET Framework 2.0 SDK, посвященному cordbg.exe.
Рис. 2.3. Отладка приложения с помощью cordbg.exe
Компоновка .NET-приложений с помощью TextPad
Бесплатный редактор Блокнот, несомненно, подходит для создания простых программ .NET, но он не может ничего предложить для повышения производительности труда разработчика. Хорошо, когда редактор, с помощью которого создаются файлы *.cs, поддерживает (как минимум) выделение цветом ключевых слов и блоков программного кода, а также предлагает интеграцию с компилятором C#. Как и следует ожидать, такой инструмент существует – это TextPad.
Редактор TextPad можно использовать для создания и компиляции программного кода не только на языке C#, но и многих других языках программирования. Главное преимущество этого продукта заключается в той, что он, с одной стороны, очень прост в использовании, а с другой – обеспечивает достаточно широкие возможности для упрощения процесса создания программного кода.
Чтобы получить TextPad, перейдите на страницу http://www.textpad.com и загрузите текущую версию этого редактора (во время создания нашей книги это была версия 4.7.3). Установив этот редактор, вы сразу получите полноценную версию TextPad с полным набором его возможностей, но знайте, что этот продукт не бесплатен. Пока вы не купите лицензию (ее стоимость около $30 для одного пользователя), вы будете видеть "дружеские напоминания" при каждом запуске этого приложения.
Активизация цветовой схемы C#
Изначально редактор TextPad не настроен на понимание ключевых слов C# и работу с сsc.exe. Чтобы настроить его соответствующим образом, нужно установить подходящее расширение. Откройте страницу http://www.textpad.com/add-ons/syna2g.html и загрузите файл csharp8.zip по ссылке C# 2005. Соответствующее расширение учитывает новые ключевые слова, введенные в C# 2005 (в отличие от файла, загружаемого по ссылке C#, в котором учитываются только возможности C# 1.1).
Развернув архив csharp8.zip, поместите копию извлеченного файла csharp8.syn в подкаталог Samples каталога инсталляции TextPad (например, в C:\Program Files\TextPad 4\Samples). Затем запустите TextPad и с помощью New Document Wizard (Мастер создания нового документа) выполните следующие действия.
1. Выберите Configured New Document Class из меню.
2. Введите имя C# 2.0 в поле редактирования Document class name (Имя документа класса).
3. Затем введите *.cs в поле редактирования Class members (Члены класса).
4. Активизируйте подсветку синтаксиса, выберите csharp8.syn из раскрывающегося списка и закройте окно мастера.
Теперь вы можете настроить поддержку C# в TextPad, используя узел Document Classes (Классы документа), доступный из меню Configure→Preferences (рис. 2.4).
Рис. 2.4. Установка параметров редактора TextPad
Настройка фильтра файлов *.cs
Следующим шагом конфигураций является создание фильтра для файлов исходного кода C#, отображаемых в диалоговых окнах Open (Открытие документа) и Save (Сохранение документа).
1. Сначала выберите Configure→Preferences из меню, а затем – элемент File Name Filters (Фильтры имен файлов) дерева просмотра.
2. Щелкните на кнопке New (Создать), а затем введите C# в поле Description (Описание) и *.cs в текстовый блок Wild cards (Групповые символы).
3. Переместите свой новый фильтр в начало списка, используя для этого кнопку Move Up (Вверх), а затем щелкните на кнопке ОК.
Создайте новый файл (используйте File→New) и сохраните его в подходящем месте на диске (например, в папке C:\TextPadTestApp) под именем TextPadTest.cs. Затем введите тривиальное определение класса (рис. 2.5).
Рис. 2.5. Файл TextPadTest.cs
Подключение csc.exe
Последним из оcновных шагов конфигурации редактора TextPad будет связь с сsc.exe которая позволит компилировать C#-файлы. С этой целью можно, например, выбрать Tools→Run из меню. Вы увидите диалоговое окно, которое позволит указать имя соответствующей программы и необходимые флаги командной строки. Так, чтобы скомпилировать TextPadTest.cs в выполняемый консольный файл .NET, выполните следующие шаги.
1. Введите полный путь к файлу csc.exe в текстовое поле Command (Команда), например C:\Windows\Microsoft.NET\Framework\v2.0.502l5\csc.exe.
2. Необходимые опции командной строки введите в текстовое поле Parameters (Параметры) – например, /out:myАрр.exe *.сs. Для упрощения процесса настройки можно указать ответный файл (например, @myInput.rsp).
3. В текстовом поле Initial folder (Исходный каталог) укажите каталог содержащий входные файлы (для нашего примера это с:\TextPadTestApp).
4. Если вы хотите, чтобы редактор TextPad захватывал вывод компилятора (а не показывал его в отдельном командном окне), установите флажок Capture Output (Захват вывода).
На риc. 2.6 показаны все необходимые для вашего примера установки компиляции.
Рис. 2.6. Установка параметров команды Run
Свою программу вы можете запустить либо с помощью двойного щелчка на имени ее выполняемого файла в программе Проводник Windows, либо с помощью выбора Tools→Run из меню редактора TextPad, указав myApp.exe в качестве текущей команды (рис. 2.7).
Рис. 2.7. Указание редактору TextPad запустить myApp.exe
После щелчка на кнопке ОК вы должны увидеть вывод программы ("Hello from TextPad"), отображенный в документе Command Results (Результаты команды).
Ассоциация команд с пунктами меню
Редактор TextPad также позволяет создавать пункты пользовательского меню, представляющие заданные команды. Для выполнения компиляции всех C#-файлов в текущем каталоге мы создадим новый пункт меню Compile C# Console (Консоль компиляции C#) в меню Tools (Сервис).
1. Сначала выберите Configured Preferences из меню, а затем – элемент Tools дерева просмотра.
2. С помощью кнопки Add (Добавить) выберите Program (Программа) и укажите полный путь к csc.exe.
3. Вместо csc.exe можно указать для меню более информативную строку, – например Compile C# Console, – щелкнув на соответствующем имени, после чего следует щелкнуть на кнопке ОК.
4. Наконец, выберите Configure→Preferences из меню еще раз, но на этот перейдите к элементу Compile C# Console узла Tools и укажите значение *.cs в поле Parameters (Параметры), рис. 2.8.
Рис. 2.8. Создание элемента меню Tools
Теперь вы получите возможность компилировать все файлы C# из текущего каталога с помощью нового пункта меню Tools.
Использование фрагментов программного кода C#
Перед использованием TextPad следует упомянуть еще об одном бесплатном расширений, которое вы можете установить. Перейдите на страницу http://www.textpad.com/add-ons/cliplibs.html и загрузите файл csharp_l.zip с библиотекой фрагментов C#, которую предлагает Шон Гефарт (Sean Gephardt). Извлеките из архива файл csharp.tсl и поместите этот файл в подкаталог Samples. Снова запустив TextPad, вы обнаружите новую библиотеку фрагментов программного кода C Sharp Helpers, доступную из раскрывающегося списка Clip Library (Библиотека фрагментов), рис. 2.9. С помощью двойного щелчка на любом из ее элементов вы можете добавить соответствующий программный код C# в той точке активного документа, где в настоящий момент находится курсор.
Рис. 2.9. Фрагменты программного кода C# в TextPad
Наверное, вы не станете возражать, что по сравнению с программой Блокнот и командной строкой использование редактора TextPad – шаг в правильном направлении. Однако TextPad (пока что) не предлагает возможности IntelliSense для программного кода C#, графических средств разработки, шаблонов проектов и средств работы с базами данных. Чтобы представить такие возможности, рассмотрим следующий инструмент .NET-разработкш SharpDevelop.
Компоновка .NET-приложений с помощью SharpDevelop
SharpDevelop является интегрированной средой разработки с открытым исходным кодом и богатыми возможностями, которые вы можете использовать для создания компоновочных блоков .NET на основе C#, VB .NET, Managed Extensions для C++ или CIL. Кроме того, что эта среда разработки совершенно бесплатна, следует отметить то, что она целиком создана на языке C#. Причем вы можете либо загрузить и скомпилировать необходимые файлы *.cs самостоятельно, либо использовать готовую программу setup.exe, которая установит SharpDevelop на вашей машине. Оба дистрибутива можно загрузить со страниц http:// www.icsharpcode.net/OpenSource/SD/Download.
После установки SharpDevelop выбор меню File→New→Combine позволит указать вид (и язык .NET) проекта, который вы хотите создать. В терминах SharpDevelop combine (комбинат) обозначает отдельную коллекцию проектов – то, что в Visual Studio называется solution, т.е. решение. Предположим, что вы указали C#-прило-жение для Windows и назвали его MySDWinApp (рис. 2.10).
Рис. 2.10. Диалоговое окно создания проекта в SharpDevelop
Замечание. Приложение SharpDevelop версии 1.0 настроена на использование компилятора C# 1.1. Чтобы использовать новый возможности языка C# 2005 и пространства имён .NET Framework 2.0, выберите Project→Project options из меню и укажите новую версию компилятора на странице настроек Runtime/Compiler (Среда выполнения/компилятор).
Возможности SharpDevelop
Среда разработки SharpDevelop предлагает разнообразные возможности повышения производительности труда программиста, и во многих отношениях эта среда разработки столь же богата возможностями, как и Visual Studio .NET 2003 (но не настолько, как Visual Studio 2005). Вот список основных преимуществ SharpDevelop:
• поддержка компиляторов C# от Microsoft и Mono;
• возможности IntelliSense и расширения программного кода;
• наличие диалогового окна Add Reference (Добавление ссылки) для ссылок на внешние компоновочные блоки, включая компоновочные блоки, установленные в GAG (Global Assembly Cache – глобальный кэш компоновочных блоков);
• наличие инструментов визуального проектирования Windows Forms;
• различные окна (в SharpDevelop они называются scouts – разведчики) для обзора структуры проекта и его составляющих:
• интегрированная утилита браузера объектов – Assembly Scout (Разведчик компоновочных блоков);
• утилиты для работы с базами данных;
• утилита конвертирования программного кода C# в VB .NET (и наоборот):
• интеграция с NUnit (утилита тестирования .NET-модулей) и NAnt (утилита компоновки .NET):
• интеграция с документацией .NET Framework SDK.
Впечатляюще для бесплатной IDE, не так ли? В этой главе мы не собираемся обсуждать каждый из указанных пунктов подробно, но давайте рассмотрим наиболее интересные из них. Если вас интересуют подробности, то заметим, что SharpDevelop предлагает очень подробную документацию, доступную при выборе Help→Help Topics из меню.
Окна проектов и классов
Создав новый комбинат, вы можете использовать окно Projects для просмотра файлов, ссылок и ресурсов соответcтвующих проектов (рис. 2.11).
Рис. 2.11. Окно проектов
Чтобы в текущем проекте сослаться на внешний компоновочный блок, в окне Projects щелкните правой кнопкой мыши на пиктограмме References (Ссылки) и из появившегося контекстного меню выберите Add Reference (Добавить ссылку). После этого на вкладке GAC или .NET Assembly Browser (Обзор компоновочных блоков .NET) вы сможете выбрать компоновочный блок, размещенный, соответственно, в GAC или в другом месте (рис. 2.12).
Рис. 2.12. Диалоговое окно добавления ссылок в SharpDevelop
Окно Classes обеспечивает объектно-ориентированный взгляд на комбинат, отображая пространства имен, типы и члены типов, определенные в рамках проекта (рис. 2.13).
Рис. 2.13. Окно классов
Двойной щелчок на любом элементе открывает соответствующий файл, помещая курсор мыши на определение элемента.
Обзор компоновочных блоков
Утилита Assembly Scout [Разведчик компоновочных блоков), доступная из меню View, предлагает обзор компоновочных блоков, на которые имеются ссылки в проекте. Это средство предлагает информацию в двух панелях, Левая панель предлагает дерево просмотра, позволяющее "войти" внутрь компоновочного блока, чтобы увидеть пространства имен и соответствующие типы (рис. 2.14).
Рис. 2.14. Просмотр компоновочных блоков в окне Assembly Scout
Правая панель утилиты позволяет увидеть содержимое элемента, выбранного в левой панели. При этом можно увидеть не только основные характеристики элемента, используя для этого вкладку Info (Информация), но и соответствующий программный код CIL. Можно также сохранить определение элемента в файле XML.
Инструменты проектирования Windows Forms
Windows Forms является средством создания приложений, возможности которого мы рассмотрим позже. А сейчас, чтобы продолжить рассмотрение SharpDevelop, щелкните на ярлыке вкладки Design внизу окна программного кода MainForm.cs. Откроется интегрированное окно проектирования Windows Forms,
С помощью элементов из раздела Windows Forms в окне Tools можно построить графический интерфейс (GUI) для создаваемой формы. Для примера поместите один элемент типа Button (кнопка) в свою главную форму, сначала выбрав пиктограмму Button, а затем щелкнув в окне проектирования. Для изменения вида любого элемента, можно использовать окно Properties (Свойства), которое активизируется с помощью выбора View→Properties из меню (рис. 2.15). Выберите Button из раскрывающегося списка этого окна и укажите нужные параметры для свойств этого типа (например, BackСolor или Text).
Рис. 2.15. Окно свойств
В этом же окне можно указать параметры обработки событий соответствующего элемента графического интерфейса. Для этого сначала щелкните на пиктограмме с изображением молнии (вверху окна свойств), а затем выберите из раскрывающегося списка графический элемент, с которым вы хотите работать (в данном случае это Button). Наконец, задайте правила обработки события Click (щелчок), напечатав имя метода, который должен вызываться при каждом щелчке пользователя на данной кнопке (рис. 2.16).
Рис. 2.16. Установка правил обработки событий в окне свойств
После нажатия клавиши ‹Enter› SharpDevelop сгенерирует программный код заглушки для вашего нового метода. Для данного примера добавите в программу обработки события следующий программный код.
void ButtonClicked(object sender, System.EventArgs e) {
// Поместим в заголовок формы новое сообщение.
this.Text = "Прекратите щелкать на моей кнопке!";
}
Теперь можно запустить программу на выполнение (выбрав Debug→Run из меню). Ясно, что в данном случае при щелчке на кнопке мы должны увидеть изменившийся заголовок окна формы.
Сейчас вы должны обладать достаточной информацией для того, чтобы начать использование интегрированной среды разработки SharpDevelop. Я надеюсь, что вы смогли представить себе ее основные возможности, хотя, очевидно, этот инструмент может предложить гораздо больше, чем было показано здесь.
Компоновка .NET-приложений с помощью Visual C# 2005 Express
Летом 2004 года Microsoft предложила совершенно новую серию IDE-продуктов, обозначенную еловом "Express" (см. http://msdn.microsoft.com/express). На сегодня выпущено шесть пакетов этого семейства.
• Visual Web Developer 2005 Express. "Облегченный" вариант средств разработки динамических Web-узлов и Web-сервисов XML, использующих ASP.NET 2.0.
• Visual Basic 2005 Express. Инструменты программирования, идеальные для программистов без большого опыта, которые хотят научиться строить .NET-приложения с помощью дружественного синтаксиса Visual Basic .NET.
• Visual C# 2005 Express. Visual C++ 2005 Express и Visual J# 2005 Express. Специальные инструменты разработки для учащихся и энтузиастов, предпочитающих изучать основы информатики в рамках синтаксиса соответствующего языка.
• SQL Server 2005 Express. Система управления базами данных начального уровня, предназначенная для любителей, энтузиастов и учащихся-разработчиков.
Замечание. Во время подготовки этой книги к печати семейство продуктов Express в виде бета-версий предлагалось совершенно бесплатно.
По большому счету продукты серии Express являются "редуцированными" версиями их аналогов из Visual Studio 2005 и предназначены главным образом для любителей .NET и учащихся. Как и в SharpDevelop, в Visual C# 2005 Express предлагаются различные средства просмотра, окно проектирования Windows Forms, диалоговое окно Add References (Добавление ссылок), возможности IntelliSense и шаблоны расширения программного кода. Кроме того, в Visual C# 2005 Express предлагается несколько (очень важных) возможностей, в настоящее время в SharpDevelop недоступных, а именно:
• интегрированный графический отладчик;
• средства упрощения доступа к Web-сервисам XML.
Ввиду того, что по виду и принципам использования Visual C# 2005 Express очень похож на Visual Studio 2005 (и в некоторой степени на SharpDevelop), здесь обсуждение указанной среды разработки не предлагается. Если вы хотите узнать об этом продукте больше, прочитайте мою статью "An Introduction to Programming Using Microsoft Visual C# 2005 Express Edition" (Введение в программирование с помощью Microsoft Visual C# 2005 Express Edition), доступную на страницах .
Компоновка .NET-приложений с помощью Visual Studio 2005
Если вы являетесь профессиональным разработчиком программного обеспечения .NET, очень велика вероятность того, что ваш работодатель согласится купить для вас лучшую интегрированную систему разработки от Microsoft – Visual Studio 2005 (http://msdn.microsoft.com/vstudio). Этот инструмент по своим возможностям существенно превосходит все другие IDE, рассмотренные в этой главе. Конечно же, это отражается и на его цене, которая зависит от приобретаемой вами версии Visual Studio 2005. Нетрудно догадаться, что каждая версия предлагает свой уникальный набор возможностей.
В дальнейшем при изложении материала книги будет предполагаться, что вы предпочли использовать в качестве среды разработки Visual Studio 2005. С другой стороны, и вы должны это понимать, что обладание копией Visual Studio 2005 для изучения материала книги не является обязательным. Самой большой проблемой Из тех. с которыми вы можете столкнуться в таком случае, это обсуждение опций, которых нет в вашей среде разработки. Но программный код всех примеров данной книги должен компилироваться с помощью любого выбранного вами инструмента разработки.
Замечание. Загрузив исходный код примеров этой книги из раздела Downloads (загрузка) Web-узла Apress (http://www.apress.com), вы сможете открывать программный код примеров в Visual Studio 2005 с помощью двойного щелчка на соответствующем файле *.sln. Если вы не используете Visual Studio 2005, вам придется вручную настроить свою среду разработки так, чтобы вы могли выполнить компиляцию соответствующих файлов *.cs.
Возможности Visual Studio 2005
Как и следует ожидать, Visual Studio 2005 содержит все необходимые средства проектирования, средства доступа к базам данных, утилиты обзора проектов и объектов, а также интегрированную систему справки. Но, в отличие от средств разработки, которые были рассмотрены выше. Visual Studio 2005 предлагает много дополнительных возможностей. Вот список некоторых из них.
• Средства визуального проектирования/редактирования XML
• Поддержка разработки программ для мобильных устройств (например, для смартфонов и КПК)
• Поддержка разработки программ для Microsoft Office
• Возможность записи изменений исходного документа и просмотра таких изменений
• Интегрированная поддержка факторизации программного кода
• XML-библиотека расширений программного кода
• Визуальные средства построения классов и утилиты тестирования объектов
• Окно определений программного кода, которое предлагается вместо утилиты Windows Forms Class Viewer, wincv.exe, предлагавшейся в .NET версии 1.1 и более ранних версий
Честно говоря, Visual Studio 2005 предлагает так много возможностей, что для их полного описания требуется отдельная книга (по объему больше этой). Наша книга решает другие задачи. Тем не менее, я счел целесообразным потратить несколько страниц на описание самых главных усовершенствований, предложенных в Visual Studio 2005. По мере чтения материала книги вы будете получать дополнительную информацию о возможностях этой интегрированной среды разработки.
Утилита обзора решений
Если вы следуете указаниям этой главы, то создайте новое консольное приложение C# (с именем Vs2005Example), выбрав File→New→Project из меню. Утилита Solution Explorer (Утилита обзора решений), доступная из меню View, позволяет просматривать множество файлов и компоновочных блоков, из которых составлен текущий проект (рис. 2.17).
Рис. 2.17. Окно обзора решений
Обратите внимание на то, что папка References (Ссылки) в окне Solution Explorer отображает список компоновочных блоков, на которые вы ссылаетесь в настоящий момент (консольные проекты по умолчанию ссылаются на System.dll, System.Data.dll и System.Xml.dll). Если нужно сослаться на другие компоновочные блоки, щелкните правой кнопкой мыши на папке References и выберите из контекстного меню Add Reference (Добавить ссылку). В появившемся диалоговом окне вы сможете выбрать нужный вам компоновочный блок.
Замечание. В Visual Studio 2005 позволяется указывать ссылки на выполняемые компоновочные блоки (в отличие от Visual Studio .NET 2003, где в данном контексте можно было использовать только библиотеки программного кода *.dll).
Наконец, обратите внимание на пиктограмму Properties (Свойства) в окне Solution Explorer. В результате двойного щелчка на ней появляется окно расширенного редактора конфигурации проекта (рис. 2.18).
Рис. 2.18. Окно редактирования свойств проекта
Возможности изменения параметров проекта в окне Project Properties (Свойства проекта) будут обсуждаться в книге по мере необходимости. Но даже при беглом его изучении становится ясно, что в нем можно установить параметры безопасности, изменить имя компоновочного блока, указать ресурсы командной строки и задать конфигурацию учета событий компиляции.
Утилита обзора классов
Следующим инструментом, который мы собираемся рассмотреть, является утилита Class View (утилита обзора классов), и ее тоже можно загрузить из меню View. Как и в случае SharpDevelop, эта утилита обеспечивает возможность обзора всех типов, входящих в текущий проект, с объектно-ориентированной точки зрения. Верхняя панель соответствующего окна отображает множество пространств имен и их типов, а нижняя панель представляет члены выбранного в настоящий момент типа (рис. 2.19).
Рис. 2.19. Окно обзора классов
Окно определений программного кода
Если вы имеете опыт программирования в .NET 1.1, то должны знать об утилите Windows Forms Class Viewer, wincv.exe (утилита обзора классов Windows Forms). Этот инструмент позволяет задать имя .NET-типа и просмотреть его C#-определение. В версии .NET 2.0 утилиты wincv.exe уже нет, но зато есть усовершенствованная версия этого средства, интегрированная в Visual C# 2005 Express и Visual Studio 2005. Соответствующее окно Code Definition (Окно определений программного кода) можно открыть через меню View. Поместите курсор мыши на любой из типов в программном коде C#, и вы увидите определение соответствующего типа. Например, если щелкнуть на слове "string" в рамках метода Main(), будет показано определение типа класса System.String (рис. 2.20).
Рис. 2.20. Окно определений программного кода
Утилита обзора объектов
Вы должны помнить из главы 1, что в Visual Studio 2005 есть утилита для просмотра компоновочных блоков, на которые ссылается проект. Активизируйте окно Object Browser с помощью меню View→Other Windows, а затем выберите компоновочный блок, который вы желаете изучить (рис. 2.21).
Интегрированная поддержка факторизации программного кода
Одним из главных усовершенствований, предлагаемых в Visual Studio 2006, является встроенная поддержка факторизации программного кода. Говоря упрощенно, факторизация означает формальный "механический" процесс усовершенствования существующего базового кода. В прошлом процесс факторизации предполагал огромные объемы ручного труда. В Visual Studio 2005 значительная часть соответствующей работы выполняется автоматически. Используя меню Refaсtor (Факторизация), соответствующие комбинации клавиш, смарт-теги и/или вызовы контекстного меню с помощью щелчков мыши, вы можете придать своему программному коду совершенно новый вид. затратив на это минимум усилий. В табл. 2.4 приведены некоторые общие команды факторизации, распознаваемые в Visual Studio 2005.
Рис. 2.21. Утилита обзора объектов в Visual Studio 2005
Таблица 2.4. Факторизация в Visual Studio 2005
Метод факторизации | Описание |
Extract Method (выделение метода) | Позволяет определить новый метод на основе выделенных операторов программного кода |
Encapsulate Field (инкапсуляция поля) | Превращает открытое поле в приватное, инкапсулированное в свойство C# |
Extract Interface (выделение интерфейса) | Определяет новый интерфейсный тип на основе множества существующих членов типа |
Reorder Parameters (перестановка параметров) | Обеспечивает изменение порядка следования аргументов |
Remove Parameters (удаление параметров) | Удаляет данный аргумент из списка параметров |
Rename (переименование) | Позволяет переименовать лексему программного кода (метод, поле, локальную переменную и т.д.) |
Promote Local Variable to Parameter | (перемещение локальной переменной в параметр) Перемещает локальную переменную в набор параметров определяемого метода |
Чтобы проиллюстрировать возможности применения средств факторизации на практике, добавьте в метод Main() следующий программный код.
static void Main(string[] args) {
// Определение консольного интерфейса (CUI)
Console.Title = "Мое приложение".;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine("*************************************");
Cоnsole.WriteLine("******** Это мое приложение! ********");
Console.WriteLine("*************************************");
Console.BackgroundColor = ConsoleColor.Black;
// Ожидание нажатия клавиши для завершения работы.
Console.ReadLine();
}
Этот программный код вполне работоспособен, но представьте себе, что вы хотите отображать генерируемую им подсказку в разных местах вашей программы. Вместо того чтобы вводить вручную операторы определения интерфейса снова и снова, было бы идеально иметь помощника, который мог бы делать это за вас. К счастью, в данном случае вы можете применить к существующему программному коду метод факторизации Extract Method (Выделение метода). Сначала в окне редактора выберите все операторы программного кода (за исключением последнего вызова Console.ReadLine()). Затем щелкните правой кнопкой мыши и из появившегося контекстного меню Refactor выберите опцию Extract Method. В появившемся диалоговом окне укажите имя нового метода – ConfigurеCUI(). В результате вы обнаружите, что теперь метод Main() вызывает новый сгенерированный метод ConfigureCUI(), содержащий ранее выделенный программный код.
class Program {
static void Main (string[] args) {
ConfigureCUI();
// Ожидание нажатия клавиши для завершения работы.
Cоnsole.ReadLine();
}
private static void ConfigureCUI() {
// Определение консольного интерфейса (CUI)
Console.Title = "Мое приложение";
Console.ForegroundColor = ConsoleColor.Yellow;
Console.BackgroundColor = ConsoleColor.Blue;
Console.WriteLine("*************************************");
Cоnsole.WriteLine("******** Это мое приложение! ********");
Console.WriteLine("*************************************");
Console.BackgroundColor = ConsoleColor.Black;
}
}
Замечание, Если вы хотите знать больше о процессе факторизации и ее поддержке в Visual Studio 2005, прочитайте мою статью "Refactoring C# Code Using Visual Studio 2005" (Факторизация программного кода C# в Visual Studio 2005), доступную на страницах .
Фрагменты программного кода и окружения
В Visual Studio 2005 (как и в Visual C# 2005 Express) предлагаются разнообразные возможности автоматического добавления сложных блоков программного кода C# с помощью выбора вариантов меню, контекстно-зависимых щелчков кнопкой мыши и/или комбинаций клавиш. Число доступных расширений программного кода весьма впечатляюще и может быть разбито на две главные группы.
• Фрагменты программного кода. Это шаблоны блоков программного кода, вставляемые в том месте, где размещается курсор мыши.
• Окружения. Это шаблоны окружений, в которые помещаются выделенные блоки операторов в рамках соответствующего контекста.
Чтобы воспользоваться соответствующими функциональными возможностями, щелкните правой кнопкой мыши на пустой строке в пределах метода Main() и активизируйте меню Insert Snippet (Вставка фрагмента). Выбрав соответствующий пункт меню, вы увидите, что указанный программный код будет добавлен автоматически (нажмите клавишу ‹Esc›, чтобы скрыть всплывающее меню).
Если вместо этого щелкнуть правой кнопкой мыши и выбрать пункт меню Surround With (Окружить с помощью…), вы увидите другой подобный список опций. Найдите время и без спешки исследуйте встроенные шаблоны расширений программного кода, так как с их помощью можно значительно ускорить процесс разработки программ.
Замечание. Bce шаблоны расширений программного кода представляют собой XML-описания программного кода, генерируемые средствами IDE. В Visual Studio 2005 (и в Visual C# 2005 Express) вы можете создавать свои собственные шаблоны. Подробности этого процесса описаны в моей статье "Investigating Code Snippet Technology" (Исследование технологии применения фрагментов программного кода), которую можно найти на страницах .
Средства визуального проектирования классов
В Visual Studio 2005 есть возможность конструировать классы визуально (в Visual C# 2005 Express такой возможности нет). Утилита Class Designer позволяет просматривать и изменять взаимосвязи типов (классов, интерфейсов, структур, перечней и делегатов), включенных в проект. С помощью этого инструмента можно визуально добавлять, модифицировать и удалять члены типов, а результаты модификации будут отображаться в соответствующем C#-файле. Аналогично, если изменить данный C#-файл, соответствующие изменения будут отражены в окне диаграммы классов.
Для работы с этими возможностями Visual Studio 2005 сначала нужно создать новый файл диаграммы классов. Это можно сделать по-разному, и один из вариантов – щелчок на кнопке View Class Diagram (Просмотр диаграммы классов), которая размещается вверху справа в окне Solution Explorer (рис. 2.22).
Рис. 2.22. Создание файла диаграммы классов
После этого вы увидите пиктограммы классов, входящих в ваш проект. Щелчок на изображении стрелки будет показывать или скрывать члены типа (см. рис. 2.23).
Рис. 2.23. Просмотр диаграммы классов
Эту утилиту удобно использовать с двумя другими возможностями Visual Studio 2005 – окном Class Details (активизируется из меню View→Other Windows) и разделом Class Designer панели инструментов (активизируется из меню View→Toolboх). Окно Class Details не только показывает структуру выбранного в настоящий момент элемента диаграммы, но и позволяет модифицировать существующие и вставлять новые члены класса (рис. 2.24).
Рис. 2.24. Окно содержимого классов
Панель инструментов (рис. 2.25) позволяет с помощью визуальных средств вставлять в проект новые типы из раздела Class Designer (и создавать связи между этими типами). (Чтобы этот раздел панели инструментов был видимым, окно диаграммы классов должно быть активным.) При этом IDE автоматически создает новые определения C#-типов в фоновом режиме.
Рис. 2.25. Вставка нового класса с помощью визуальных средств Class Designer
Для примера перетащите новый класс из раздела Class Designer панели инструментов в окно диаграммы классов, В соответствующем диалоговом окне укажите для этого нового класса имя Car (автомобиль). Затем, используя окно Class Details, добавьте в класс открытое строковое поле, назначив, ему имя petName (имя любимца), как показано на рис. 2.26.
Рис. 2.26. Добавление поля в окно содержимого класса
Если теперь взглянуть на определение C#-класса Car, вы увидите, что оно соответствующим образом обновлено.
public class Car {
// Использовать открытые данные без необходимости
// не рекомендуется, но здесь это сделано для простоты
public string petName;
}
Добавьте в окно диаграммы классов еще один новый класс с именем SportsCar (спортивный автомобиль). Затем в разделе Class Designer панели инструментов выберите пункт Inheritance (Наследование) и щелкните на пиктограмме класса SportsCar. Не отпуская левую кнопку мыши, переместите указатель на пиктограмму класса Car. Если все было сделано правильно, вы должны получить класс SportsCar, являющийся производным класса Car (рис. 2.27).
Чтобы закончить построение примера, добавьте в сгенерированный класс SportsCar открытый метод PrintPetName().
public class SportsCar: Car {
public void PrintPetName() {
petName = "Фредди";
Console.WriteLine("Имя этой машины: {0}", petName);
}
}
Рис. 2.27. Визуальное получение производного класса из класса, имеющегося в наличии
Стенд тестирования объектов (ОТВ-тестер)
Еще одним удобным инструментом визуальный разработки в Visual Studio 2005 является ОТВ-тестер (Object Test Bench – стенд тестирования объектов). Этот инструмент IDE позволяет быстро создать экземпляр класса и выполнить вызов его членов без компиляции и выполнения всего приложения. Это очень удобно в тех случаях, когда вы хотите проверить работу конкретного метода, но в обычных условиях для этого требуется "пройти" через десятки строк программного кода.
Для работы с ОТВ-тестером щелкните правой кнопкой мыши на типе, который вы создаете с помощью окна проектирования классов. Например, щелкните правой кнопкой мыши на типе SportsCar и из появившегося контекстного меню выберите Create Instance→SportsCar(), Появится диалоговое окно, которое позволит задать имя вашей временной объектной переменной (и, если нужно, предоставить конструктору необходимые аргументы). После завершения процесса вы обнаружите свой объект в рамках IDE. Щелкните правой кнопкой мыши на пиктограмме объекта и вызовите метод PrintPetName() (рис. 2.28).
Рис. 2.28. Стенд тестирования объектов в Visual Studio 2005
Вы увидите сообщение "Имя этой машины: Фредди", которое появится в Visual Studio 2005 в рамках консоли Quick.
Интегрированная справочная система
В завершение давайте обсудим возможность Visual Studio 2005, которая по определению должна быть удобной. Речь здесь идет об интегрированной справочной системе. Документация .NET Framework 2.0 SDK исключительно хороша, очень удобна для чтения и содержит очень много полезной информации. С учетом огромного количества встроенных .NET-типов (их число измеряется тысячами) вы должны быть готовы закатать рукава, чтобы погрузиться в глубины предлагаемой документации. Если же вы к этому не готовы, то при разработке .NET-приложений вы обречены на бесконечные трудности и многочисленные разочарования.
В Visual Studio 2005 предлагается окно Dynamic Help (Динамическая справка), которое (динамически!) изменяет свое содержимое в зависимости от того, какой элемент (окно, меню, ключевое слово исходного кода и т.д.) является активным в настоящий момент. Например, если вы поместите Курсор мыши на класс Console, окно Dynamic Help отобразит набор разделов справки, имеющих отношение к типу System.Console.
Также следует знать об одном очень важном подкаталоге документации .NET Framework 2.0 SDK. В разделе .NET Development→NET Framework SDK→Class Library Reference документации вы найдете полные описания всех пространств имен из библиотек базовых классов .NET (рис. 2.29).
Рис. 2.29. Справка по библиотеке базовых классов .NET
Каждый "узел" здесь определяет набор типов данного пространства имен, члены данного типа и параметры каждого члена. Более того, при просмотре страницы помощи для данного типа сообщается имя компоновочного блока и пространства имен, которые содержат рассматриваемый тип (соответствующая информация размещается в верхней части страницы). Я предполагаю, что при изучении материала данной книги вы доберетесь до очень и очень глубоко спрятанных узлов, чтобы получить важные дополнительные сведения о рассматриваемых объектах.
Дополнительные средства разработки .NET-приложений
В заключение хотелось бы обратить ваше внимание на ряд инструментов разработки .NET, которые могут дополнить функциональные возможности выбранной вами IDE. Многие из упомянутых здесь инструментов имеют открытый исходный код, и все они бесплатны. В этой книге нет места для подробного описания этих утилит, но в табл. 2.5 представлены описания инструментов, которые я считаю чрезвычайно полезными, а также URL-адреса, по которым можно найти дополнительную информацию.
Таблица 2.5. Подборка средств разработки .NET-приложений
Название | Описание | URL-адрес |
FxCop | Этот инструмент входит в разряд обязательных для любого разработчика .NET-приложений, заинтересованного в совершенствовании своих программ. FxCop проверит любой компоновочный блок .NET на соответствие официальным требованиям и рекомендациям Microsoft .NET | http://www.gotdotnet.com/tеаm/fxcop |
Lab Roeder's Refleсtor для .NET | Этот усовершенствованный декомпилятор/браузер объектов NET позволяет проанализировать реализацию любого .NET-типа, использующего CIL, C#, Object Pascal .NET (Delphi) или Visual Basic .NET | http://www.aisto.сom/roeder/dotfnet |
NAnt | NAnt является .NET-эквивалентом Ant – популярного автоматизированного средства создания модулей Java. NAnt позволяет определять и выполнять подробные сценарии компоновки, используя синтаксис XML | http://sourceforge.net/projects/nant |
NDoc C | помощью NDoc можно генерировать файлы документации для программного кода C# (или компилированных компоновочных блоков .NET) в самых популярных форматах (*.chm MSDN, XML, HTML, Javаdoc и LaTeX) | http://sourseforge.net/projects/ndoc |
NUnit | NUnit является.NET-эквивалентом инструмента JUnit, предназначенного для тестирования Java-модулей. С помощью NUnit можно упростить процесс проверки управляемого программного кода | http://www.nunit.org |
Vil | Воспринимайте Vil как "старшего брата" разработчика .NET. Этот инструмент проанализирует программный код .NET и предложит ряд рекомендаций относительно того, как улучшить его о помощью факторизации, структурированной обработки исключений и т.д. | http://www.Ibot.com |
Замечание. Функциональные возможности FxCop сейчас интегрированы в Visual Studio 2005. Чтобы в этом убедиться, выполните двойной щелчок на пиктограмме Properties (Свойства) в окне Solution Explorer и активизируйте вкладку Code Analysis (Анализ программного кода).
Резюме
Как видите, в ваше полное распоряжение предоставлено множество новых игрушек! Целью этой главы было описание самых популярных средств создания программ на языке C#, которые могут ускорить процесс разработки. Обсуждение началось с описания того, как сгенерировать компоновочный блок .NET, не имея ничего, кроме бесплатного компилятора C# и программы Блокнот. Затем мы рассмотрели приложение TextPad и выяснили, как настроить этот инструмент на редактирование и компиляцию файлов *.cs с программным кодом.
Были также рассмотрены три интегрированные среды разработки с более широкими возможностями: сначала SharpDevelop с открытым исходным кодом, затем Visual C# 2005 Express и, наконец. Visual Studio 2005 от Microsoft. Эта глава только коснулась всего богатства функциональных возможностей каждого из этих инструментов, чтобы вы могли приступить к самостоятельному изучению выбранной вами среды разработки. В завершение был рассмотрен ряд инструментов разработки .NET с открытым исходным кодом, которые могут предложить разработчику дополнительные возможности.