Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Объектно-ориентированное программирование.-6

.pdf
Скачиваний:
6
Добавлен:
05.02.2023
Размер:
4.5 Mб
Скачать

та (0). Запуск без отладки в среде Visual Studio настроен таким образом, что после завершения программы ожидается нажатие любой клавиши, в остальных же случаях консольное окно сразу закрывается. Чтобы этого не происходило, код можно несколько модифицировать:

using System;

namespace Sample_2_3

{

class Program

{

public static int Main(string[] args)

{

Console.WriteLine("Hello, World!"); Console.ReadKey(true);

return 0;

}

}

}

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

2.3.5. Анализ исходного кода

Проанализируем набранный нами код, сравнив его с программой на языке C++, выполняющей аналогичные функции:

#include <stdio.h> // или <iostream> #include <conio.h> // или <cconio>

int main(int argc, char *args[])

{

printf("Hello, World!"); // или cout << "Hello, World!" getch();

return 0;

}

1) using System

В языке C++, чтобы получить доступ к библиотечным функциям, мы подключали к программе соответствующие библиотеки (директивой препроцессора #include). В языке C# нет аналогичного языку C++ понятия библиотек, подключаются только пространства имен. При этом можно использовать все объекты, содержащиеся в подключенном пространстве имен, и не важно, в каком именно файле они описаны (объекты пространства имен могут быть размещены в нескольких различных файлах). В данном случае мы подключаем пространство имен System, которое содержит класс Console, обеспечивающий консольный ввод и вывод, а также классы типов данных (int, string и

51

т.д.).

2) namespace Sample_2_3

Далее в программе на языке C# мы описывали пространство имен Sample_2_3. В принципе, делать это не обязательно – если объект разместить вне пространства имен, он автоматически будет включен в пространство имен по умолчанию. Но считается хорошим тоном не поступать таким образом. Включение объекта в пространство имен упрощает его использование из других модулей в дальнейшем. В языке C++ тоже можно использовать пространства имен, но т.к. в основе модулей языка лежали библиотеки, пространства имен использовались реже. Речь не идет о языке Visual C++ .NET, который подвергся некоторой модификации.

3) class Program

В отличие от языка C++, все объекты языка C# являются классами. Соответственно, нельзя описать процедуру или функцию вне класса, все процедуры и функции должны быть описаны как методы класса, в т.ч. и функция main. Название у данного класса может быть любым.

4) public static int Main(string[] args)

Т.к. Main – это метод класса, то для него должен быть указан модификатор доступа. В данном случае это public. Как и в языке C++, по умолчанию используется модификатор private. Модификатор static играет ту же роль, что и в языке C++, т.е. указывает, что метод является статическим и может быть вызван без создания экземпляра класса. Это обязательное требование для функции Main, т.к. компилятор автоматически не создает экземпляр класса, в котором эта функция описана (в нашем случае – Program). Имя функции, в отличие от языка C++, пишется с заглавной буквы. Возвращает функция, как и в языке C++, целое число – код возврата операционной системе. Аргументы функции Main играют ту же роль, это список параметров командной строки. Но, если в языке C++ было два аргумента (количество аргументов и массив указателей на них), то в языке C# аргумент один. Почему

– станет понятно после изучения свойств массивов. Если анализ аргументов командной строки в программе не предусмотрен, скобки можно оставить пустыми:

public static int Main()

Также следует отметить, что в языке C++ описание метода может находиться в классе, а реализация – как здесь же в классе (тогда компилятор не-

52

явно подразумевает модификатор inline), так и вне класса. Чаще всего описания находятся в заголовочных файлах (.H), а реализация – в исходных (.CPP). В языке C# выбора нет – реализация метода должна находиться в классе сразу после его описания, а понятие заголовочного файла отсутствует.

5) Console.WriteLine("Hello, World!")

Т.к. основу языка C# составляют классы, то и процедура вывода на консоль является методом класса (класса Console). Этот метод описан с модификаторами public static, поэтому доступен извне класса, и экземпляр класса Console для его вызова создавать не обязательно. Форматирование вывода в данном классе отличается от форматирования вывода функцией printf и классом ostream (экземпляром которого является cout), и мы его подробно рассмотрим далее. В отличие от языка C++, статические функции вызываются с использованием оператора «.» (класс.метод), в то время как в C++ предусмотрено два варианта: с использованием оператора «.» (экземпляр.метод) и оператора «::» (класс::метод).

6) Console.ReadKey(true)

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

System.Console.ReadKey(true);

Пространство имен обязательно указывается только в том случае, если присутствует неоднозначность – несколько подключенных пространств имен содержат объект (класс, структуру и т.д.) с одинаковым именем.

7) return 0

Смысл этого оператора тот же, что и в языке C++. Возвращаем операционной системе код успешного завершения программы. Опять же, как и в языке C++ этот код можно не возвращать, тогда в описании функции Main меняем int на void:

public static void Main()

{

Console.WriteLine("Hello, World!"); Console.ReadKey(true);

}

53

2.3.6. Анализ кода MSIL

Итак, посмотрим, какой же код MSIL генерируется при компиляции нашего приложения. Для этого запустим Microsoft .NET Framework IL Disassembler (ILDASM). Запустить его можно из среды SharpDevelop, выбрав пункт меню «Tool» → «IL Dasm».

Если ссылка на ILDASM отсутствует в меню среды разработки, то можно, во-первых, запустить эту программу самостоятельно:

• Зайти в папку

<папка Program Files>\Microsoft SDKs\Windows\<номер версии SDK>\bin

(см. рис. 2.19) и запустить исполняемый файл ildasm.exe. В этой же папке располагается справка по этой программе – DASMHLP.HLP.

Рис. 2.19 – Расположение программы ILDASM

• Ввести в командной строке или в меню запуска программы (Win+R) «ildasm». Если пути к папке SDK прописаны в системе, то дизассемблер бу-

54

дет запущен. Если нет, следует воспользоваться первым вариантом. Во-вторых, в среде Visual Studio существует возможность добавлять

новые инструменты в меню «Сервис». Для этого следует выбрать пункт меню «Сервис → Внешние инструменты…». Появится диалог, изображенный на рисунке 2.20. Нажимаем кнопку «Добавить», придумываем название для нового пункта меню (амперсандом можно пометить символ-акселератор), указываем путь к файлу ildasm.exe и исходный каталог (просто копируем название каталога из поля «Команда»). Ставим галочку «Использовать окно вывода» (чтобы при запуске ILDASM не появлялось консольное окно). После этого нажимаем «OK», и в меню «Сервис» появляется новый пункт «MSIL Disassembler».

Рис. 2.20 – Добавление нового внешнего инструмента

Запустив ILDASM (рис. 2.21), выберем в меню «Файл» выберите команду «Открыть». В появившемся диалоговом окне откроем папку с приложением Sample_2_3_text.exe (хотя можно взять любую другую версию), которое мы создали чуть раньше, и выберем его.

55

Рис. 2.21 – Главное окно ILDASM

В главном окне появится древовидное представление управляемого двоичного кода. В файле справки можно посмотреть значки, которыми ILDASM помечает те или иные компоненты .NET-приложения (рис. 2.22).

Рис. 2.22 – Условные обозначения ILDASM

Сравнив эти значки с представлением приложения «Hello, World!» в ILDASM, можно заметить, что приложение состоит из декларации, одного пространства имен (Sample_2_3), одного класса (Program), а также двух методов (конструктора класса и статического метода Main) и кое-какой инфор-

56

мации о классе.

В приложении «Hello, World!» наиболее интересен метод Main. Дважды щелкните значок метода Main в древовидной структуре приложения, и ILDASM выведет окно, отображающее MSIL-код метода Main (рис. 2.23).

Рис. 2.23 – MSIL-код метода Main

В этом коде можно видеть кое-что, характерное для любого .NETприложения:

.method public hidebysig static int32 Main(string[] args) cil managed

{

.entrypoint

 

// Размер кода:

18 (0x12)

.maxstack 1

 

.locals init (int32 V_0)

IL_0000: nop

 

IL_0001: ldstr

"Hello, World!"

IL_0006: call

void [mscorlib]System.Console::WriteLine(string)

IL_000b: nop

 

IL_000c: ldc.i4.0

 

IL_000d: stloc.0

 

IL_000e: br.s

IL_0010

IL_0010: ldloc.0 IL_0011: ret

} // end of method Program::Main

Первая строка содержит описание метода Main с помощью ключевого слова .method. Можно заметить, что в этом описании есть модификаторы public и static, с которыми был описан метод Main. Кроме того, метод имеет атрибут managed (управляемый код). Это важная отличительная особенность,

57

так как на C# можно создать и «неуправляемый» (unmanaged), или «небезопасный» (unsafe), код.

Ключевое слово .entrypoint в следующей строке MSIL-кода указывает на то, что данный метод является точкой входа приложения. Когда исполняющая среда запускает приложение, управление программой передается коду, следующему за этой точкой.

Вызывают интерес и исполняемые коды в строках IL_0001 и IL_0006. В первой команда ldstr (load string) загружает в стек неизменяемый литерал («Hello, World!»). В следующей строке вызывается метод System.Console::WriteLine. Заметьте: к имени метода добавлено имя сборки (assembly), в которой описан этот метод (mscorlib). Такой уровень детализации MSIL хорош тем, что вы без труда напишете утилиту, которая выявит связи в программе и отобразит информацию о файлах, требующихся для правильной работы приложения. Кроме того, вы можете определить число аргументов метода и их типы. В нашем случае метод System.Console.WriteLine принимает объект System.String, который перед вызовом метода должен быть помещен в стек. И, наконец, в строке IL_0011 находится исполняемый MSILкод ret – код возврата из метода.

Чтобы выяснить, какой код находится в файле EXE или DLL – управляемый или нет, попробуйте открыть его в ILDASM. Файл, содержащий MSIL-код и декларацию, будет открыт. В ином случае вы получите сообщение об ошибке (рис. 2.24).

Рис. 2.24 – Ошибка при открытии файла без заголовка CLR

2.3.7. Файлы с примерами

Пример к § 2.3, набранный в текстовом редакторе (вместе с пакетным файлом, необходимыми для его компиляции) находится в файле

Samples\2.3\Sample_2_3_text.cs. Пакетный файл называется cs23.bat. Если на вашей машине среда .Net Framework установлена в другой папке, нежели у автора, потребуется модификация этого файла. Файл cs.bat позволяет осуще-

58

ствить компиляцию программы на языке C# в консоли, указав имя файла с программой в качестве параметра.

Решение для SharpDevelop с примером к данному разделу располагается в папке Samples\2.3\Sample_2_3_spec. Структура решения во многом совпадает с таковой у Visual Studio 2008 – файл решения имеет имя

Sample_2_3_spec.sln, а файл с программой – Program.cs. Решение для Visual Studio 2008 располагается в папке Samples\2.3\Sample_2_3_msvs.

В дальнейшем все примеры будут разрабатываться в Visual Studio 2008. Однако ничто не мешает компилировать их с консоли (правильно указав параметры компиляции) или в других совместимых средах. Даже если в используемой среде формат решения (и/или проекта) будет другим, можно создавать в их рамках пустые проекты и добавлять к ним файлы с программой

Program.cs из решений для Visual Studio.

59

§ 2.4. Среда разработки

Рассмотрим основы работы в среде разработки Microsoft Visual Studio

2008.

2.4.1. Организация проекта

По умолчанию все файлы и папки пустого проекта, назовем его «Project», располагаются в папке «Project» (если не создавался отдельный каталог для решения). Это:

1.Project.sln – файл решения. Содержит список проектов решения, конфигурации построения решения и т.п.

2.Project.suo – пользовательские настройки решения. В данный файл записываются все параметры, связанные с решением, так что каждый раз при открывании решения включаются произведенные пользователем настройки (в т.ч. положение окон и диалогов, открытые файлы и т.д.).

3.Project.csproj – настройки проекта (задаваемые в диалоге свойств проекта, меню «Проект» → «Свойства: Project…», где Project – имя текущего проекта).

4.Program.cs – исходный файл с программой на языке C#.

5.Properties\AssemblyInfo.cs – файл на языке C#, содержащий сведения

осборке.

6.Папки bin, obj. Создаются при компиляции. Содержат исполняемые файлы, динамические библиотеки (в зависимости от типа проекта), различные вспомогательные файлы компиляции и компоновки. В принципе, их можно удалять, при повторном построении решения компилятор их сгенерирует снова.

Все исходные файлы и ссылки сборки можно видеть в окне обозревателя решений (рис. 2.25).

Здесь можно исключить файлы из проекта или удалить их, переименовать или открыть в редакторе кода. Двойной щелчок мышью по файлу с исходным кодом открывает его в редакторе. В файле AssemblyInfo.cs можно настроить некоторые свойства сборки – заголовок, описание, копирайт, версия и т.д. Все настройки имеют вид

[assembly: <класс>(<параметры>)]

60