Суббота, 18.05.2024, 14:26
Приветствую Вас Гость | RSS
Форма входа
Поиск
Календарь
«  Май 2024  »
ПнВтСрЧтПтСбВс
  12345
6789101112
13141516171819
20212223242526
2728293031
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Charles Petzold ".NET Book Zero" Глава 4. Редактирование, компиляция, запуск, дизасемблирован

Файл, содержащий код C# обычно имеет расширение файла .cs от "C Sharp". Далее мы приводим простой пример (имя файла, выделенное полужирным шрифтом в верхней части - не является частью программы):

FirstProgram.cs

//---------------------------------------------
// FirstProgram.cs (c) 2006 by Charles Petzold
//---------------------------------------------

class FirstProgram
{
   public static void Main()
   {
      System.Console.WriteLine("Hello, Microsoft .NET Framework!");
   }
}

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

Хотя вы, скорее всего, в конечном итоге будете использовать Microsoft Visual Studio для разработки .NET программ, это не единственный вариант. Вы на самом деле можете редактировать, компилировать и запускать программы .NET из командной строки MS-DOS. Во многих отношениях, компиляция программы на C# в командной строке очень похоже на то, как вы, возможно, компилировали программы на C в командной строке два десятка лет назад.

Компиляция программы .NET в командной строке MS-DOS может показаться странным и эксцентричной практикой в современных графических средах, таких как Windows, но я думаю, что для начинающего .NET программиста это достаточно важно, чтобы попробовать это хотя бы один раз. По крайней мере, вы разуверитесь в понимании того, что вам нужны мощные ресурсы Visual Studio для компиляции всех программ на .NET, которые вы когда-нибудь напишете.

(Некоторая информация из этой главы, не применима к .NET 1.1 SDK. Если  вы используете его, вы должны выбрать пункт Tools в "Microsoft .NET Framework SDK v1.1", в стартовом меню ОС Windows, для получения информации о командной строке, IL дизассемблере и IL ассемблере.)

И Visual Studio 2005 и .NET 2.0, и 3.0 SDK, создают ярлык в меню Пуск Windows для запуска окна командной строки. Его вы и должны использовать. Стандартное окно командной строки сложнее использовать для компиляции, потому что, оно не имеет собственных переменных среды, настроенных таким образом, чтобы MS-DOS мог найти C# компилятор.

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

notepad

и запустится Блокнот Windows. Или, вы можете ввести имя файла в качестве аргумента Блокнота Windows, например:

notepad firstprogram.cs

Тогда Блокнот спросит вас, хотите ли вы создать файл.

Наберите в Блокноте, программу показанную ранее. C# является чувствительным к регистру языком. Убедитесь, что вы вводите слова class, public, static, и void полностью в нижнем регистре. Убедитесь, что вы вводите слова Main, System, и Console, с заглавной буквы, а остальные в нижнем регистре. Убедитесь, что WriteLine имеет начальную заглавную букву и заглавную букву посередине. Вы можете напечатать имя класса - FirstProgram, любым удобным образом (или вы можете использовать и другое имя), но не вставляйте пробел в имя и не начинайте имя с цифры. В имя не нужно включать строки, начинающиеся с двойной косой черты.

Сохраните файл в Блокноте под именем firstprogram.cs, или под каким-нибудь другим именем, которое вы предпочитаете. (Вам не обязательно выходить из Блокнота, после этого, но вы должны обязательно сохранить файл.) Затем, в командной строке, запустите компилятор C#, который является программой с именем csc.exe:

csc firstprogram.cs

C# компилятор считывает исходный код и (если все хорошо) создаёт файл с именем firstprogram.exe, который вы можете запустить следующим образом:

firstprogram

Программа отображает текстовое приветствие, а затем завершает работу.

Я упомянул во второй главе, что исполняемый файл .NET в действительности содержит Common Intermediate Language (CIL) код. .NET SDK включает в себя инструмент под названием IL Disassembler (ildasm.exe), который разбирает исполняемый .NET файл и показывает вам содержание CIL. В меню Пуск, найдите группу SDK, а затем инструмент под названием "IL Disassembler". Запустите его. Или, просто введите:

ildasm

в командной строке. В диалоговом окне "Открыть Файл", перейдите в каталог, который вы использовали, и загрузите FirstProgram.exe. Откройте класс FirstProgram и дважды щелкните Main. Это ваша программа на CIL. Команда ldstr загружает текстовую строку в стек, а затем вызывать команду System.Console.WriteLine (но с синтаксисом, больше напоминающим C++), для отображения строки. Когда вы запускаете программу, .NET Common Language Runtime (CLR) компилирует CIL в машинный код, подходящий для вашего конкретного процессора.

Если вам привлекательно изучение CIL, вы можете больше узнать об этом по ссылке:

http://www.ecma-international.org/publications/standards/Ecma-335.htm

.NET SDK включает в себя ассемблер для CIL называющийся ilasm.exe. Программы, написанные непосредственно в CIL так же являются управляемыми и портируемыми, как и программы, написанные на C#.

Конечно, большинство программистов .NET не знаю CIL полностью, и еще меньше знают CIL в такой степени, чтобы быть в состоянии написать код в нем. Тем не менее, иногда поучительно и показательно изучать CIL код, который генерирует C# компилятор, и в этой книге я буду иногда обращать ваше внимание на него.

Теперь давайте перейдем от программирования командной строки в другую крайность, запустив Visual Studio 2005 или Visual C# 2005 Express Edition.

В меню выберите "Файл" (File), а затем "Создать проект" (New Project). В Visual Studio, сначала выберите Visual C# и окно слева. В любом издании, выберите "Пустой проект" (Empty Project). Дайте проекту имя (FirstProgram, скажем). В Visual Studio, вы должны будете выбрать каталог для проекта и нужно снять флажок с "Создать каталог для решения" (Create Directory For Solution). В Visual C# Express Edition, вы сможете выбрать каталог, когда вы будете сохранять проект.

В обозревателе решений (Solution Explorer) справа, щелкните правой кнопкой мыши на проекте FirstProgram и выберите "Добавить" - "Создать элемент". (Или выберете "Добавить" - "Новый элемент" в меню "Проект".) Выберите файл кода (Code File) и дайте файлу имя FirstProgram.cs.

Теперь введите программу, показанную ранее. Во время набора, вы увидите, что Visual Studio пробует предугадать, то что вам нужно. Когда вы наберёте System и сделаете паузу, например, перед вами появится список типов в этом пространстве имен, а когда вы наберете Console и остановитесь, вы получите список членов класса Console. Это Intellisense Visual Studio, и вы можете заметить, что он вызывает привыкание, а затем, будете ненавидеть себя за то, что слишком много полагаетесь на него .

Вы можете скомпилировать и запустить программу, выбрав "Запуск без отладки" ( Start Without Debugging) в меню "Отладка" (Debug) или нажав Ctrl-F5. Программа будет скомпилирована и запустится в окне с командной строкой.

То, что вы сделали - заключается в создании проекта Visual Studio под названием First-Program, который располагается в каталоге FirstProgram. Проект, в целом, создает единый исполняемый файл или одну динамическую библиотеку. (В Visual Studio, несколько смежных проектов могут быть объединены в "решение" (solution)). Проект может содержать один или несколько файлов исходного кода C#. В простейшем случае, проект содержит один файл C#, а для удобства файлу C#, как правило, дается такое же имя, как у проекта, но с расширением ".cs".

Вернувшись в командную строку или в Windows Explorer, вы можете увидеть, что Visual Studio создал файл проекта в каталоге FirstProgram с именем FirstProgram.csproj. Это XML-файл, который ссылается на файл .cs и содержит всю информацию необходимую Visual Studio для поддержки проекта и его компиляции.

Во время компиляции, Visual Studio также создал несколько промежуточных файлов в папке FirstProgram в подкаталоге с именем obj. Исполняемый файл находится в подкаталоге "Release ", либо "Debug" в зависимости от конфигурации, которую вы выбрали в Visual Studio.

Если вы работаете с .NET 3.0, вернитесь в командную строку. Убедитесь, что файл FirstProgram.csproj находится в текущем каталоге и выполните команду:

msbuild firstprogram.csproj

Программа MSBuild скомпилирует проект и (по умолчанию) поместит исполняемый файл в каталог bin\Debug.

Программа MSBuild появилась в .NET 3.0 отчасти потому, что программы Windows Presentation Foundation могут быть построены из двух файлов: C# и XAML (Extensible Application Markup Language) файлов. Программа MSBuild вызывает компилятор C# и другие инструменты, для сборки целого исполняемого файла. Вы можете написать свой собственный файл проекта - .csproj, если хотите.

Между двумя крайностями, командной строкой и Visual Studio, есть и другие инструменты программирования .NET, такие, как мой KeyOfCSharp.exe, который вы можете скачать отсюда:

http://www.charlespetzold.com/keycs

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

http://www.charlespetzold.com/dotnet

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

Давайте посмотрим на листинг программы снова:

FirstProgram.cs

//---------------------------------------------
// FirstProgram.cs (c) 2006 by Charles Petzold
//---------------------------------------------

class FirstProgram
{
   public static void Main()
   {
      System.Console.WriteLine("Hello, Microsoft .NET Framework!");
   }
}

Вначале находится несколько однострочных комментариев, начинающихся с привычного двойного слэша. C# также поддерживает многострочные или частичнострочные комментарии, ограниченные "/ *" и "* /".

Весь код в C# программе должен находиться в каком-либо классе или структуре. Наша программа определяет класс (обозначается ключевым словом class) под названием FirstProgram:

class FirstProgram
{
   //содержимое класса
}

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

struct FirstProgram
{
   //содержимое структуры
}

Программа будет компилироваться и выполнять то же самое.

Она является общей для определения класса или структуры с ключевым словом public:

public class FirstProgram
{
   //содержимое класса
}

Тем не менее, использование ключевого слова public с классом, как правило, не требуется в программном коде. (Есть некоторые случаи, когда это необходимо.) Ключевое слово public применяется к классу, в котором находится гораздо больше кода, и который требуется для динамических библиотек.

При создании этого проекта в Visual Studio, я использовал имя проекта, которое является таким же, как и имя C# файла, который совпадает с именем класса, определенного в этом файле. Ни одно из этих совпадений имен не обязательно. На самом деле, файл C# может содержать несколько определений классов, ни один из которых может не совпадать с именем файла. Класс также может быть разделена между несколькими файлами, имена  которых не обязательно будут совпадает с именем класса. Ни одно из этих имен не должно обязательно быть такими же, как имя проекта.

Просто, чтобы избежать путаницы, я вообще люблю, ограничить свои файлы исходных кодов на C# одним простым классом и структурой, а также использовать имя файла, совпадающее с именем класса или структуры. (Но иногда я буду нарушать это правило в книге.)

В классе (или в структуре) FirstProgram находится единственный метод с именем Main. Точка входа в программу на C# это - всегда метод с именем Main, и он должен начинаться с заглавной буквы. C# является чувствительным к регистру языком.

Метод Main определяется ключевыми словами public и static.

public static void Main()
{
   //содержимое метода
}

Ключевое слово public показывает, что метод является видимым извне класса, в котором он определен. Ключевое слово public, в действительности, не обязательно для метода Main, и программа будет компилироваться и работать нормально без него. Иногда я использую public с Main, а иногда и нет. Когда - это загадка.

Ключевое слово static означает, что этот метод связан с самим классом, а не с экземпляром этого класса. Класс - это как дозатор мороженого, а экземпляры класса - мороженое. К сожалению, наша простая программа не делает какого-либо мороженого. Здесь нет ключевых слов экземпляра, поскольку статические методы, обычно, скорее исключение, чем правило. Мир имеет гораздо больше мороженного, чем дозаторов мороженого, и, как правило мороженое более интересно.

Этот особенный метод Main не имеет параметров - на это указывают пустые скобки после Main - и ничего не возвращает при вызове, об этом свидетельствует ключевое слово void. (Вы можете определить Main, как имеющее параметр, являющийся массивом строк текста, которые устанавливаются - аргументам командной строки программы. Main также, может возвращать целое число при прекращении кода. См. Спецификацию языка C#, § 3.1 для более подробной информации).

Тело метода ограничивают фигурные скобки. Все тело этого метода Main составляет выражение:

System.Console.WriteLine("Hello, Microsoft .NET Framework!");

Как и в C, и в C++, выражения в C# заканчиваются точкой с запятой. Этот оператор является вызовом метода. Аргументом является строка, заключенная в двойные кавычки. Строковые литералы в C# ограничиваются одной строкой. Другими словами, двойные кавычки, ограничивающие строку должны быть на той же строке. (Если вам необходимо, разбить длинную строку на несколько строк, вы можете объединить несколько строковых литералов с помощью оператора плюс (я покажу это в следующей главе)).

Хотя строковые литералы должны находиться в одной строке, C# может свободно отформатировать их другим способом. Можно так:

class
   FirstProgram
              {
public
           static
    void
              Main
     (
                       )
    {
   System.
       Console
     .
        WriteLine
                 (
"Hello, Microsoft .NET Framework!"
            )
             ;
        }
              }

Или так:

class FirstProgram{public static void Main(
){System.Console.WriteLine("Hello, Microsoft .NET Framework!");}}

Однако, если вы будете кодить, таким образом, никто не будет с вами дружить.

FirstProgram не делает ничего, кроме вызова метода с именем System.Console.WriteLine. Это полное имя метода. Как у писателей романов, методы в .NET Framework, как правило, имеют три названия:

- System - пространство имен..

- Console - класс в этом пространстве имен.

- WriteLine - является метод в этом классе.

В документации классов .NET вы обнаружите, что класс Console на самом деле имеет много методов с именами WriteLine. Эти различные варианты метода WriteLine известны как - перегрузка. Один вариант, который я использую в этой программе, определяется так (исключены разрывы строк, указанные в документации):

public static void WriteLine(string value)

Здесь, снова встречается ключевое слово static, и это означает то, что WriteLine является методом, связанным с классом Console, а не с экземпляром класса Console. Ключевое слово static означает, что метод должен использоваться предварённым именем его класса, в котором он определён, разделенным точкой. Класс предваряется именем пространства, в котором определен класс, также разделенный точкой.

Где находится код System.Console.WriteLine который фактически и отображает текст на консоли? Если вы посмотрите на первую страницу документации для класса Console, вы увидите в верхней части следующее:

Assembly: mscorlib (in mscorlib.dll)

Это означает, что код класса Console находится в сборке с именем mscorlib. Сборка может состоять из нескольких файлов, но в данном случае здесь только один файл, которым является динамическая библиотека mscorlib.dll. Файл mscorlib.dll очень важен в .NET. Имя файла в одно время расшифровывалось как "Microsoft Common Object Runtime Library", но сейчас оно расшифровывается как "Multilanguage Standard Common Object Runtime Library". Это главная DLL, для библиотек классов в .NET, и она содержит все основные классы и структуры .NET.

Как вы знаете, когда вы собираете C или C++ программу, вам, как правило, необходима директива #include в верхней части листинга, которая ссылается на файл заголовка. Подключаемый файл содержит в себе прототипы функций для компилятора.

Компилятору C# не нужны файлы заголовков. Во время компиляции, компилятор C# имеет доступ к файлу mscorlib.dll напрямую и получает информацию из метаданных файла, относящуюся ко всем классам и другим типам, определенных в нем. C# компилятор устанавливает, что mscorlib.dll действительно содержит класс с именем Console, в пространстве имен с именем System, и методом с именем WriteLine, который принимает один аргумент типа string. Компилятор C# может определить, что вызов WriteLine правильный, и компилятор устанавливает ссылку на mscorlib собранную в исполняемый файл.

Intellisense также работает с помощью ссылок на mscorlib.dll и получает информацию из DLL о пространствах имен, типах и членах.

Как вы, наверное, знаете, компиляция C или C++ программы - это просто первый шаг в создании исполняемого файла. Затем вы должны (явно или неявно) запустить линкер, который получает доступ к файлам библиотек. Традиционно, код стандартных динамических библиотек вставляется прямо в исполняемый файл. Для кода в DLL файлах, вставляются только ссылки.

Компилятор C# не требует библиотеку файлов. Потому что компилятор уже обращается к актуальной DLL, он может вставлять ссылки на эту DLL в исполняемый файл. В то время, когда программа выполняется, CLR связывает программу с фактическим вызовом метода из mscorlib.dll.

Многие основные классы и структуры включены в mscorlib.dll. Как вы выходите за пределы командной строки, вы начнете сталкиваться с классами, которые хранятся в других DLL библиотеках. Например, классы в пространстве имен System.Windows.Forms хранятся в сборке System.Windows.Forms, которой является DLL - system.windows.forms.dll.

Компилятор C# имеет доступ к mscorlib.dll по умолчанию, но для доступа к другим DLL библиотекам, вы должны указать компилятору сборку, в которой расположены классы. Они известны как ссылки. В Visual Studio, щелкните правой кнопкой мыши Ссылки (References ) под именем проекта в окне Обозреватель решений (Solution Explorer) и выберите Добавить ссылку (Add Reference). Или выберите Add Reference из меню Project. (Для компилятора командной строки, необходимо указать ссылки с ключом компилятора /r).

Может показаться большим трудом постоянно набирать System.Console.WriteLine только для того, чтобы отобразить строку текста, и вот поэтому язык С# поддерживает директиву, которая немного уменьшает набор на клавиатуре. Эта программа представляет собой функциональный эквивалент для программы, показанной ранее:

SecondProgram.cs

//----------------------------------------------
// SecondProgram.cs (c) 2006 by Charles Petzold
//----------------------------------------------
using System;

class SecondProgram
{
    public static void Main()
    {
        Console.WriteLine("Hello, Microsoft .NET Framework!");
    }
}

Вызову Console.WriteLine больше не предшествует пространство имен System. Это стало возможным благодаря верхней строке, которая начинается с ключевого слова using. Эта строка называется директивой, потому что она не является, строго говоря, выражением. Она должна находиться перед любым определением типа в файле, например, класса. Директива по существу говорит компилятору C#, что если он не может найти статический метод Console.WriteLine, он должен попробовать добавить в начало System, чтобы получить System.Console.WriteLine и попробуйте найти его.

Конечно, с помощью директивы using точно не уменьшишь размер программы, но, если у вас очень много вызовов WriteLine, это, безусловно, будет полезным. Все примеры программ отныне будет иметь, директиву using для пространства имен System, а иногда и для других пространств имен. Директива using это не заголовочный файл, и не библиотечный файл. Это и не ссылка на файл.

Директива using указывает только на пространство имен, и, обязательное наличие директивы using не требуется в C# программе. Немного отличающаяся форма директивы using определяет псевдоним, который позволяет ещё больше уменьшить повторный ввод кода.

ThirdProgram.cs

//---------------------------------------------
// ThirdProgram.cs (c) 2006 by Charles Petzold
//---------------------------------------------
using C = System.Console;

class ThirdProgram
{
    public static void Main()
    {
        C.WriteLine("Hello, Microsoft .NET Framework!");
    }
}

Теперь любая ссылка на класс System.Console может быть сокращен до простой заглавной буквы С. Это, примерно, как сокращения, которые у нас получаются по ходу книги. (Следующий шаг будет заключаться в определении Вашего собственного короткого названия метода, который затем вызывает WriteLine).

Я должен предупредить вас о том насколько ограничены псевдонимы объектов: директивой using не выполняет замену System.Console для любых и всех случаев большой буквы С в коде. В директиве using, правая сторона знака равенства должна быть именем или типом, и этот пример только тогда срабатывает, когда компилятор не может найти класс названный C, с методом по именем WriteLine.

Также имейте в виду, что культура C# не поощряет использование таких методов, так как это делает ваш код более неясным, чем он должен быть. Используйте эту форму объявления using, в первую очередь для ситуации, когда вам нужно ссылаться на классы с таким же именем из двух разных пространств имен.

Например, предположим, что вы покупаете две необходимые библиотеки классов в виде библиотек DLL из "Bovary Enterprises" и "Karenina Software". Обе эти библиотеки содержат класс с именем SuperString, реализованный совершенно по-разному в каждой DLL, но полезный вам в обоих вариантах. Использование двух классов SuperString - не проблема, потому что обе компании определяют уникальные пространства имен для своих классов.

Программисты из Бовари поставили свой класс SuperString в пространство имен под названием BovaryEnterprises.VeryUsefulLibrary. Да, пространство имен содержит встроенный период, и это соответствует  общепринятой практике. В первую очередь идёт название компании, за которым следует название продукта. Код, разработанный в Бовари похож на что-то вроде этого:

namespace BoveryEnterprises.VeryUsefulLibrary
{
    public class SuperString
    {
        ...
    }
}

Умные программисты из Карениной также пользуются принятым соглашением по именованию и разместили свой класс SuperString в пространстве имен KareninaSoftware.HandyDandyLibrary.

Таким образом, при использовании обоих этих библиотек в вашей программе, вы можете ссылаться на любой класс SuperString, просто используя полное имя, которое является либо

BovaryEnterprises.VeryUsefulLibrary.SuperString

Или

KareninaSoftware.HandyDandyLibrary.SuperString

И вот здесь, псевдоним в форме директивы using, вступает в игру. Для упрощения ввод текста, вы можете включить следующие две using директивы в вашу программу:

using Emma = BovaryEnterprises.VeryUsefulLibrary;
using Anna = KareninaSoftware.HandyDandyLibrary;

Теперь вы можете обратиться к двум классам, как

Emma.SuperString

и:

Anna.SuperString

Если вы пишете код для DLL, и особенно если вы намерены сделать эту DLL доступной для других, вы должны будете поместить всё в пространство имен, которое идентифицирует вашу компанию и продукт.

Вы также можете использовать определения пространства имен в программном коде, предназначенном не для DLL, но там это не так жизненно важно. В первых книгах по .NET программированию, которые я написал, я не использовать в программах пространства имен. В своей последней книге на Windows Presentation Foundation, я использовал пространство имен в коде программы, оно состояло из моего имени, за которым следовало имя проекта. Я сделал это по двум причинам. Самое главное, при интеграции C# кода с XAML, это помогает программному коду быть в пространстве имен. Кроме того, когда один проект ссылается код из другого проекта (как делал я в своей книге по WPF), пространства имен помогают определить, где находится код, на который идут ссылки.

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

FourthProgram.cs

//----------------------------------------------
// FourthProgram.cs (c) 2006 by Charles Petzold
//----------------------------------------------
using System;

namespace Petzold.FourthProgram
{
    class FourthProgram
    {
        public static void Main()
        {
            Console.WriteLine("Hello, Microsoft .NET Framework!");
        }
    }
}

Тем не менее, в этой небольшой книге, это было последнее место где вы увидите определение пространства имен.


© Charles Petzold ".NET Book Zero" 2007