Добавить в цитаты Настройки чтения

Страница 255 из 371



Еще одна новинка С#, встречающаяся в начальном проекте, это атрибут [STAThread], который предшествует описанию процедуры Main. Так же, как и тэги документирования, атрибуты распознаются специальным инструментарием и становятся частью метаданных. Атрибуты могут быть как стандартными, так и заданными пользователем. Стандартные атрибуты используются CLR и влияют на то, как она будет выполнять проект. В данном случае атрибут [STAThread] (Single Thread Apartment) задает однопоточную модель выполнения. Об атрибутах и метаданных мы еще будем говорить подробно. Заметьте, если вы нечетко представляете, каков смысл однопоточной модели, и не хотите, чтобы в вашем тексте присутствовали непонятные для вас указания, то этот атрибут можно удалить из текста, что не отразится на выполнении.

Скажем еще несколько слов о точке входа — процедуре Main. Ее заголовок можно безболезненно упростить, удалив аргументы, которые, как правило, не задаются. Они имеют смысл, когда проект вызывается из командной строки, позволяя с помощью параметров задать нужную стратегию выполнения проекта.

Таков консольный проект, построенный по умолчанию. Функциональности у него немного. Его можно скомпилировать, выбрав соответствующий пункт из меню build. Если компиляция прошла без ошибок, то в результате будет произведена сборка и появится PE-файл в соответствующей папке Debug нашего проекта. Приложение можно запустить нажатием соответствующих клавиш (например, CTRL+F5) или выбором соответствующего пункта из меню Debug. Приложение будет выполнено под управлением CLR. В результате выполнения появится консольное окно с предложением нажать любую клавишу для закрытия окна.

Слегка изменим проект, построенный по умолчанию, добавим в него свой код и превратим его в классический проект приветствия. Нам понадобятся средства для работы с консолью — чтения с консоли (клавиатуры) и вывода на консоль (дисплей) строки текста. Библиотека FCL предоставляет для этих целей класс Console, среди многочисленных методов которого есть методы ReadLine и WriteLine с очевидной семантикой. Вот код проекта, полученный в результате моих корректировок:

using System;

namespace ConsoleHello

{

    /// <summary>

    /// Первый консольный проект — Приветствие

    /// </summary>

    class Class1

    {

        /// <summary>

        /// Точка входа. Запрашивает имя и выдает приветствие

        /// </summary>

        static void Main()

        {

             Console.WriteLine("Введите Ваше имя");

             string name;

             name = Console.ReadLine ();

             if (name=="")

                 Console.WriteLine ("Здравствуй, мир!");

             else

                 Console.WriteLine("Здравствуй, " + name +"!");

          }

     }

}

Я изменил текст в тегах <summary>, удалил атрибут и аргументы процедуры Main, добавил в ее тело операторы ввода-вывода. Благодаря предложению using, мне не требуется при вызове методов класса Console каждый раз писать System.Console. Надеюсь, что программный текст понятен без дальнейших пояснений.

В завершение первого проекта построим его XML-отчет. Для этого в свойствах проекта необходимо указать имя файла, в котором будет храниться отчет. Установка этого свойства проекта, так же как и других свойств, делается в окне Property Pages, открыть которое можно по-разному. Я обычно делаю это так: в окне Solution Explorer выделяю строку с именем проекта, а затем в окне Properties нажимаю имеющуюся там кнопку Property Pages. Затем в открывшемся окне свойств, показанном на рис. 2.3, устанавливается нужное свойство. В данном случае я задал имя файла отчета hello.xml.

Рис. 2.3. Окно Property Pages проекта и задание имени XML-отчета

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

<?xml version="1.0"?>

<doc>

<assembly>

     <name>ConsoleHello</name>

</assembly>

<members>

      <member name="T: ConsoleHello.Class1>

            <summary>

                 Первый консольный проект — Приветствие

            </summary>

       </member>

       <member name="M: ConsoleHello.Class1.Main">

             <summary>

                  Точка входа. Запрашивает имя и_выдает приветствие

             </summary>

        </member>

</members>

</doc>

Как видите, отчет описывает наш проект, точнее, сборку. Пользователь, пожелавший воспользоваться этой сборкой, из отчета поймет, что она содержит один класс, назначение которого указано в теге <summary>. Класс содержит лишь один элемент — точку входа Main с заданной спецификацией в теге <summary>.





Windows-проект

Проделаем аналогичную работу: построим Windows-проект, рассмотрим, как он выглядит по умолчанию, а затем дополним его до проекта "Приветствие". Повторяя уже описанные действия, в окне нового проекта (СМ. рис. 2.1) Я выбрал тип проекта Windows Application, дав проекту имя WindowsHello.

Как и в консольном случае, по умолчанию строится решение, содержащее единственный проект, содержащий единственное пространство имен (все три конструкции имеют совпадающие имена). В пространство имен вложен единственный класс Form1, но это уже далеко не столь простой класс, как ранее. Вначале приведу его код, а потом уже дам необходимые пояснения:

using System;

using System.Drawing;

using System.Collections;

using System.ComponentMode1;

using System.Windows.Forms;

using System.Data;

namespace WindowsHello {

{

     /// <summary>

     /// Summary description for Form1.

     /// </summary>

     public class Form1: System.Windows.Forms.Form

     {

          /// <summary>

          /// Required designer variable.

          /// </summary>

          private System.ComponentMode1.Container components = null;

          public Form1()

          {

               // Required for Windows Form Designer support

               InitializeComponent ();

               // TODO: Add any constructor code after

               // InitializeComponent call

          }

         /// <summary>

         /// Clean up any resources being used.

         /// </summary>

         protected override void Dispose(bool disposing)

         {

               if(disposing)

               {

                     if (components!= null)

                {

                        components.Dispose ();

                 }

           }

           base.Dispose(disposing);

      }

      #region Windows Form Designer generated code

      /// <summary>

      /// Required method for Designer support — do not modify

      /// the contents of this method with the code editor.

      /// </summary>

      private void InitializeComponent ()

      {

             this.components = new

                 System.ComponentMode1.Container ();