Главная страница
Навигация по странице:

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

  • Первая простая программа Настало время рассмотреть реальную C-программу. /* Это простая C-программа. Назовем ее Example.cs. */ 34

  • Использование компилятора командной строки csc.exe

  • Компилирование программы

  • Использование Visual Studio IDE

  • Обработка синтаксических ошибок

  • Небольшая вариация на тему первой программы

  • Вторая простая программа

  • Первое знакомство с инструкциями управления

  • Использование блоков кода

  • Использование точки с запятой и оформление текста программы

  • Справочник по C# Герберт Шилдт ббк 32. 973. 26018 75 Ш57 удк 681 07 Издательский дом "Вильямс" Зав редакцией


    Скачать 5.05 Mb.
    НазваниеСправочник по C# Герберт Шилдт ббк 32. 973. 26018 75 Ш57 удк 681 07 Издательский дом "Вильямс" Зав редакцией
    АнкорC #.pdf
    Дата08.12.2017
    Размер5.05 Mb.
    Формат файлаpdf
    Имя файлаC #.pdf
    ТипСправочник
    #10795
    страница3 из 52
    1   2   3   4   5   6   7   8   9   ...   52
    Глава 2
    Обзор элементов языка C#

    Глава 2. Обзор элементов языка C#
    31 амым трудным в изучении языка программирования, безусловно, является то, что ни один его элемент не существует изолированно от других. Компоненты языка работают вместе, можно сказать, в дружном “коллективе”. Такая тесная взаимосвязь усложняет рассмотрение одного аспекта C# без рассмотрения других. Зачастую обсуждение одного средства предусматривает предварительное знакомство с другим. Для преодоления подобных трудностей в этой главе приводится краткое описание таких элементов C#, как общая форма C#-программы, основные инструкции управления и операторы. При этом мы не будем углубляться в детали, а сосредоточимся на общих концепциях создания C#- программы. Большинство затронутых здесь тем более подробно рассматриваются в остальных главах части I.
    Объектно-ориентированное программирование
    Главное в языке C# — реализация принципов объектно-ориентированного
    программирования (ООП). Объектно-ориентированная методика неотделима от C#, и все
    C#-программы в какой-то степени имеют объектную ориентацию. Поэтому, прежде чем приступать к написанию даже простой Сопрограммы, необходимо понять основные принципы ООП.
    ООП — это мощный “рычаг”, позволяющий усовершенствовать процесс программирования. С момента изобретения компьютера методы программирования менялись много раз и причем коренным образом, но в основном, с целью адаптации к непрерывному повышению сложности программ. Например, программирование для первых компьютеров осуществлялось посредством набора машинных инструкций (в двоичном коде) на передней панели компьютера. Этот метод работал до тех пор, пока длина программы не превышала нескольких сот инструкций. С ростом программ был изобретен язык ассемблер, который позволил программисту писать гораздо большие и более сложные программы, используя символическое представление машинных инструкций. По мере роста программ появились языки высокого уровня (например, FORTRAN и COBOL), которые позволили программистам справляться с возрастающей сложностью программ. Когда эти первые компьютерные языки начали приближаться к критическому состоянию, было изобретено структурное программирование.
    Каждая веха в развитии программирования характеризовалась созданием методов и средств, позволяющих программисту писать все более сложные программы. С каждым шагом на этом пути изобретался новый метод, который, опираясь на самые удачные элементы предыдущих методов, вносил что-то свое, осуществляя таким образом прогресс в области программирования в целом. Примерно по такой схеме развития инструментария для программистов “дошло дело” и до объектно-ориентированного программирования. Его появлению способствовал тот факт, что реализация многих проектов начала серьезно стопориться, поскольку структурный подход уже не справлялся с поставленными задачами.
    Нужен был новый способ преодоления сложности программ, и решением этой проблемы стало объектно-ориентированное программирование.
    Объектно-ориентированное программирование вобрало в себя лучшие идеи структурного программирования и объединило их с новыми концепциями. В результате появился более совершенный способ организации программы. Если говорить в самых общих чертах, программу можно организовать одним из двух способов: опираясь либо на код (т.е. на действия, или на то, что происходит в программе), либо на данные (т.е. на то, что подвергается определенному воздействию). При использовании исключительно методов структурного программирования программы обычно организовывались с опорой на действия. Такой подход можно представить себе в виде кода, воздействующего на данные.
    С

    32
    Часть I. Язык C#
    Объектно-ориентированные программы работают совсем по-другому. Они организованы вокруг данных, а ключевой принцип такой организации гласит: именно данные должны управлять доступом к коду. В объектно-ориентированном языке программист определяет данные и код, который разрешен для выполнения действий над этими данными. Таким образом, тип данных точно определяет операции, которые могут быть к ним применены.
    Для поддержки принципов объектно-ориентированного программирования все ООП- языки, включая C#, имеют три характерных черты: инкапсуляцию, полиморфизм и наследование.
    Инкапсуляция
    Инкапсуляция — это механизм программирования, который связывает код (действия) и данные, которыми он манипулирует, и при этом предохраняет их от вмешательства извне и неправильного использования. В объектно-ориентированном языке код и данные можно связать таким образом, что будет создан автономный черный ящик. Внутри этого ящика находятся все необходимые данные и код. При таком связывании кода и данных создается объект. Другими словами, объект — это элемент, который поддерживает инкапсуляцию.
    Код, данные или обе эти составляющие объекта могут быть закрытыми внутри него или открытыми. Закрытый код или закрытые данные известны лишь остальной части этого объекта и доступны только ей. Это означает, что к закрытому коду или данным не может получить доступ никакая другая часть программы, существующая вне этого объекта. Если код или данные являются открытыми, к ним (несмотря на то, что они определены внутри объекта) могут получить доступ другие части программы. Как правило, открытые части объекта используются для обеспечения управляемого интерфейса с закрытыми элементами.
    Основной единицей инкапсуляции в C# является класс. Класс определяет форму объекта. Он задает как данные, так и код, который будет оперировать этими данными. В C# класс используется для создания объектов. Объекты — это экземпляры класса. Таким образом, класс — это по сути набор шаблонных элементов, которые показывают, как построить объект.
    Код и данные, которые составляют класс, называются членами класса. Данные, определенные в классе, называются переменными экземпляра (instance variable), а код, который оперирует этими данными, — методами-членами (member method), или просто методами. “Метод” — это термин, применяемый в C# для обозначения подпрограммы. Если вы знакомы с языками C или C++, то, вероятно, догадываетесь о том, что то, что C#- программист называет методом, C/C++-программист назовет функцией. А поскольку C# — прямой потомок C++, термин “функция” также приемлемо использовать, когда речь идет о
    C#-методе.
    Полиморфизм
    Полиморфизм (от греческого слова polymorphism, означающего “много форм”) — это качество, которое позволяет одному интерфейсу получать доступ к целому классу действий.
    Простым примером полиморфизма может послужить руль автомобиля. Руль (интерфейс) остается рулем независимо от того, какой тип рулевого механизма используется в автомобиле. Другими словами, руль работает одинаково в любом случае: оснащен ли ваш автомобиль рулевым управлением прямого действия, рулевым управлением с усилителем или реечным управлением. Таким образом, поворот руля влево заставит автомобиль поехать влево независимо от типа используемого в нем рулевого управления. Достоинство такого единообразного интерфейса состоит, безусловно, в том, что, если вы знаете, как обращаться с рулем, вы сможете водить автомобиль любого типа.

    Глава 2. Обзор элементов языка C#
    33
    Тот же принцип можно применить и к программированию. Рассмотрим, например, стек (stack), т.е. область памяти, функционирующую по принципу “последним пришел — первым обслужен”. Предположим, вы пишете программу, для которой нужно организовать три различных типа стека. Один стек предназначен для целочисленных значений, второй — для значений с плавающей точкой, а третий — для символов. В этом случае для реализации каждого стека используется один и тот же алгоритм, несмотря на различие в типах сохраняемых данных. В случае не объектно-ориентированного языка вам пришлось бы создать три набора “стековых” подпрограмм, имеющих различные имена. Но благодаря полиморфизму в среде C# можно создать один общий набор “стековых” подпрограмм, который обрабатывает все три типа стека. Иными словами, зная, как использовать один стек, можно использовать все остальные.
    Концепцию полиморфизма часто выражают такой фразой: “один интерфейс — много методов”. Это означает, что для выполнения группы подобных действий можно разработать общий интерфейс. Полиморфизм позволяет понизить степень сложности программы, предоставляя программисту возможность использовать один и тот же интерфейс для задания общего класса действий. Конкретное (нужное в том или ином случае) действие
    (метод) выбирается компилятором. Программисту нет необходимости делать это вручную.
    Его задача — правильно использовать общий интерфейс.
    Наследование
    Наследование — это процесс, благодаря которому один объект может приобретать свойства другого. Благодаря наследованию поддерживается концепция иерархической классификации. В виде управляемой иерархической (нисходящей) классификации организуется большинство областей знаний. Например, яблоки Красный Делишес являются частью классификации яблоки, которая в свою очередь является частью класса фрукты, а тот — частью еще большего класса пища. Таким образом, класс пища обладает определенными качествами (съедобность, питательность и пр.), которые применимы и к подклассу фрукты. Помимо этих качеств, класс фрукты имеет специфические характеристики (сочность, сладость и пр.), которые отличают их от других пищевых продуктов. В классе яблоки определяются качества, специфичные для яблок (растут на деревьях, не тропические и пр.). Класс Красный Делишес наследует качества всех предыдущих классов и при этом определяет качества, которые являются уникальными для этого сорта яблок.
    Если не использовать иерархическое представление признаков, для каждого объекта пришлось бы в явной форме определить все присущие ему характеристики. Но благодаря наследованию объекту нужно доопределить только те качества, которые делают его уникальным внутри его класса, поскольку он (объект) наследует общие атрибуты своего родителя. Следовательно, именно механизм наследования позволяет одному объекту представлять конкретный экземпляр более общего класса.
    Первая простая программа
    Настало время рассмотреть реальную C#-программу.
    /*
    Это простая C#-программа.
    Назовем ее Example.cs.
    */

    34
    Часть I. Язык C# using System; class Example {
    //
    Любая C#-программа начинается с вызова метода Main(). public static void Main() {
    Console.WriteLine("Простая C#-программа.");
    }
    }
    На момент написания этой книги единственной доступной средой разработки C#- программ была Visual Studio .NET. Эта среда позволяет отредактировать, скомпилировать и выполнить C#-программу, причем это можно сделать двумя способами: с помощью компилятора командной строки csc.exe или интегрированной среды разработки
    (Integrated Development Environment — IDE). Здесь описаны оба способа. (Если вы используете иной компилятор, следуйте инструкциям, приведенным в сопроводительной документации.)
    Использование компилятора командной строки csc.exe
    Несмотря на то что в случае коммерческих проектов вы, по всей вероятности, будете работать в интегрированной среде разработки Visual Studio, использование C#-компилятора командной строки — самый простой способ скомпилировать и выполнить примеры программ, приведенные в этой книге. Для создания и запуска программ с помощью C#- компилятора командной строки необходимо выполнить следующие действия.
    1. Ввести текст программы, используя любой текстовый редактор.
    2. Скомпилировать программу.
    3. Выполнить программу.
    Ввод текста программы
    Программы, представленные в этой книге, можно загрузить с Web-сайта компании
    Osborne с адресом: www.osborne.com
    . Но при желании вы можете ввести текст программ вручную. В этом случае необходимо использовать какой-нибудь текстовый редактор, например Notepad. Однако помните, что при вводе текста программ должны быть созданы исключительно текстовые файлы, а не файлы с форматированием, используемым при текстовой обработке, поскольку информация о форматировании помешает работе C#- компилятора. Введя текст приведенной выше программы, назовите соответствующий файл
    Example.cs
    Компилирование программы
    Чтобы скомпилировать программу, запустите C#-компилятор, csc.exe, указав в командной строке имя исходного файла.
    C:\>csc Example.cs
    Компилятор csc создаст файл с именем
    Example.exe
    , который будет содержать
    MSIL-версию этой программы. Хотя MSIL-код не является выполняемым, тем не менее он содержится в ехе
    -файле. При попытке выполнить файл
    Example.ехе система Common
    Language Runtime автоматически вызовет JIT-компилятор. Однако имейте в виду: если вы попытаетесь выполнить
    Example.ехе
    (или любой другой ехе
    -файл, содержащий MSIL- код) на компьютере, в котором не установлена среда .NET Framework, программа выполнена не будет ввиду отсутствия системы CLR.

    Глава 2. Обзор элементов языка C#
    35
    На заметку
    Перед запуском компилятора csc.ехе вам, возможно, придется выполнить
    пакетный файл
    vcvars32.bat,
    который обычно расположен в папке
    //Program Files/Microsoft Visual Studio.NET/Vc7/Bin.
    В качестве
    альтернативного варианта можно перейти в режим работы по приглашению
    на ввод команды. Для C# этот режим инициализируется выбором команды
    Microsoft Visual Studio .NET
    ,
    Visual Studio .NET Command Prompt
    ,
    Visual Studio
    .NET Tools из меню Пуск
    ,
    Программы, активизируемом на панели задач.
    Выполнение программы
    Для выполнения программы достаточно ввести ее имя в командную строку.
    C:\>Example
    При выполнении этой программы на экране отобразится следующая информация:
    Простая C#-программа.
    Использование Visual Studio IDE
    Теперь можно обратиться к версии 7 пакета Visual Studio .NET, поскольку Visual
    Studio IDE позволяет компилировать C#-программы. Чтобы отредактировать, скомпилировать и выполнить C#-программу с помощью интегрированной среды разработки пакета Visual Studio (версия 7), выполните следующие действия. (Если вы работаете с другой версией пакета Visual Studio, возможно, придется следовать другим инструкциям.)
    1. Создайте новый (пустой) C#-проект, выполнив команду File , New , Project
    (Файл ,Создать ,Проект).
    2. Среди представленных типов проектов (на панели Project Types (Типы проектов)) выберите вариант Visual C# Projects (Проекты Visual C#), а затем (как показано на рис. 2.1) на панели Templates (Шаблоны) — шаблон Empty Project (Пустой проект).
    Рис. 2.1. Окно New Project (Создать проект)

    36
    Часть I. Язык C#
    3. Создав проект, щелкните правой кнопкой мыши на имени проекта в окне Solution
    Explorer (Проводник решений) Затем, используя всплывающее контекстное меню, выберите команду Add , Add New Item (Добавить , Добавить новый элемент) При этом экран должен выглядеть, как показано на рис 2.2.
    4. В открывшемся диалоговом окне Add New Item (Добавить новый элемент) на панели Categories (Категории) выберите вариант Local Project Items
    (Элементы локальных проектов), а на панели Templates — шаблон Code File
    (Файл с текстом программы) При этом экран должен выглядеть, как показано на рис 2.3.
    Рис 2.2. Контекстные меню при выборе команды Add , Add New Item
    Рис 2.3. Диалоговое окно Add New Item

    Глава 2. Обзор элементов языка C#
    37
    5. Введите текст программы и сохраните файл под именем
    Example.cs
    . (Помните, что программы, представленные в этой книге, можно загрузить с Web-сайта компании Osborne с адресом: www.osborne.com
    .) После этого экран должен выглядеть, как показано на рис. 2.4.
    Рис. 2.4. Окно проекта Example.cs
    6. Скомпилируйте программу с помощью команды Build , Build Solution
    (Построить , Построить решение).
    7. Выполните программу с помощью команды Debug , Start Without Debugging
    (Отладка , Начать выполнение без отладки).
    После выполнения этой программы вы должны увидеть окно, показанное на рис. 2.5.
    Рис. 2.5. Результат выполнения программы
    На заметку
    Чтобы скомпилировать и выполнить примеры программ, представленные в
    этой книге, нет необходимости для каждой программы создавать новый
    проект. Можно использовать тот же самый C#-проект. Просто удалите
    текущий файл и добавьте новый. Затем перекомпилируйте его и выполните.
    Как уже упоминалось, короткие программы (из первой части книги) проще компилировать и выполнять, используя компилятор командной строки, но окончательный выбор, конечно, за вами.

    38
    Часть I. Язык C#
    “Разбор полетов”, или первый пример программы “под микроскопом”
    Несмотря на миниатюрные размеры, программа
    Example.cs включает ряд ключевых средств, которые применимы ко всем C#-программам. Поэтому имеет смысл подробно рассмотреть каждую часть программы, начиная с имени.
    В отличие от некоторых языков программирования (например, Java), в которых имя программного файла имеет очень большое значение, C#-программа может иметь любое имя. С таким же успехом вы могли бы назвать первую в этой книге программу не
    Example.cs
    , а, скажем,
    Sample.cs
    ,
    Test.cs или даже
    X.cs
    По соглашению для исходных файлов C#-программ используется расширение
    .cs
    , и этому соглашению вы должны следовать безоговорочно. Многие программисты называют файл программы по имени основного класса, определенного в этом файле. Поэтому (как вы, вероятно, догадались) и было выбрано имя
    Example.cs
    . Поскольку имена C#-программ могут быть произвольными, для большинства примеров программ в этой книге имена вообще не указаны. Это значит, что вы можете называть их по своему вкусу.
    Первая наша программа начинается со следующих строк.
    /*
    Это простая C#-программа.
    Назовем ее Example.cs.
    */
    Эти строки образуют комментарий. Подобно большинству других языков программирования C# позволяет вводить в исходный файл программы комментарии, содержимое которых компилятор игнорирует. С помощью комментариев описываются или разъясняются действия, выполняемые в программе, и эти разъяснения предназначаются для тех, кто будет читать исходный код. В данном случае в комментарии дается общая характеристика программы и предлагается назвать этот исходный файл именем
    Example.cs
    . Конечно, в реальных приложениях комментарии используются для разъяснения особенностей работы отдельных частей программы или конкретных действий программных средств.
    В C# поддерживается три стиля комментариев. Первый, показанный в начале рассматриваемой программы, называется многострочным. Комментарий этого типа должен начинаться символами
    /*
    и заканчиваться ими же, но в обратном порядке (
    */
    ). Все, что находится между этими парами символов, компилятор игнорирует. Комментарий этого типа, как следует из его названия, может занимать несколько строк.
    Рассмотрим следующую строку программы. using System;
    Эта строка означает, что программа использует пространство имен
    System
    . В C#
    пространство имен (namespace) определяет декларативную область. Подробнее о пространствах имен мы поговорим позже, а пока ограничимся тем, что заявленное пространство имен позволяет хранить одно множество имен отдельно от другого. Другими словами, имена, объявленные в одном пространстве имен, не будут конфликтовать с такими же именами, объявленными в другом. В нашей программе используется пространство имен
    System
    , которое зарезервировано для элементов, связанных с библиотекой классов среды
    .NET Framework, используемой языком C#. Ключевое слово

    Глава 2. Обзор элементов языка C#
    39 using
    — это своего рода заявление о том, что программа использует имена в заданном пространстве имен.
    Перейдем к следующей строке программы.
    В этой строке используется ключевое слово class
    , которое объявляет об определении нового класса. Как упоминалось выше, в C# класс — это базовая единица инкапсуляции.
    Example
    — имя определяемого класса. Определение класса заключено между открывающей (
    {
    ) и закрывающей (
    }
    ) фигурными скобками. Таким образом, элементы, расположенные между этими двумя фигурными скобками, являются членами класса. Пока мы не будем углубляться в детали определения класса, но отметим, что в C# работа программы протекает именно внутри класса. Это одна из причин, по которой все C#- программы являются объектно-ориентированными.
    Очередная строка в нашей программе представляет собой однострочный
    комментарий.
    // Любая C#-программа начинается с вызова метода Main().
    Так выглядит комментарий второго типа, поддерживаемый в C#. Однострочный комментарий начинается с пары символов
    // и заканчивается в конце строки. Как правило, программисты используют многострочные комментарии для подробных и потому более пространных разъяснений, а однострочные — для кратких (построчных) описаний происходящего в программе.
    Следующей строке стоит уделить особое внимание. public static void Main() {
    В этой строке начинается определение метода
    Main()
    . Как упоминалось выше, в C# подпрограмма называется методом (method). Предшествующий этой строке однострочный комментарий подчеркивает, что именно с этой строки и будет начато выполнение программы. Все C#-приложения начинают выполняться с вызова метода
    Main()
    . (Для сравнения: выполнение С/C++-программ начинается с обращения к функции main()
    .) В полном описании каждой части этой строки сейчас большого смысла нет, поскольку это требует глубокого понимания других средств языка C#. Но так как эта строка кода включена во многие примеры программ этой книги, придется кратко на ней остановиться.
    Ключевое слово public представляет собой спецификатор доступа (access specifier). Спецификатор доступа определяет, как другие части программы могут получать доступ к члену класса. Если объявление члена класса включает ключевое слово public
    , значит, к этому члену можно получить доступ с помощью кода, расположенного вне класса, в котором этот член объявлен. (Противоположным по значению ключевому слову public является слово private
    , которое не допускает использования соответствующего члена класса кодом, определенным вне его (члена) класса.) В данном случае метод
    Main()
    объявляется как public
    -метод, поскольку при запуске этой программы он будет вызываться внешним (по отношению к его классу) кодом (а именно операционной системой).
    На заметку
    На момент написания книги в документации на язык C# не было обозначено
    требования, чтобы
    Main()
    объявлялся как
    public
    -метод. Однако именно
    таким образом оформлены подобные объявления в примерах, включенных в
    описание пакета Visual Studio .NET. Этот способ объявления предпочитают
    использовать многие C#-программисты. Поэтому и в настоящей книге метод
    Main()
    объявляется с использованием спецификатора
    public
    . Но вы не
    должны удивляться, встретив несколько иной способ объявления метода
    Main().
    Ключевое слово static позволяет реализовать вызов метода
    Main()
    еще до создания объекта соответствующего класса. Это — очень важный момент, поскольку метод

    40
    Часть I. Язык C#
    Main()
    вызывается при запуске программы. Ключевое слово void просто сообщает компилятору о том, что метод
    Main()
    не возвращает значения. Как будет показано выше, методы могут возвращать значения. Пустые круглые скобки после имени
    Main()
    говорят о том, что методу не передается никакой информации. Как будет показано выше, методу
    Main()
    (или любому другому) можно передавать данные, которые будут им обрабатываться. Рассматриваемую строку венчает символ открывающей фигурной скобки
    (
    (
    ), который служит признаком начала тела метода
    Main()
    . Между открывающей и закрывающей фигурными скобками и должен находиться весь код, составляющий тело метода.
    Рассмотрим следующую строку программы. Обратите внимание на то, что она принадлежит телу метода
    Main()
    Console.WriteLine("Простая C#-программа.");
    Здесь реализован вывод на экран текстовой строки “Простая C#-программа.” и следующего за ней символа новой строки. Сам вывод осуществляется встроенным методом
    WriteLine()
    . В данном случае на экране будет отображена строка, переданная методу.
    Передаваемая методу информация называется аргументом. Помимо текстовых строк, метод
    WriteLine()
    может отображать и данные других типов.
    Console
    — это имя встроенного класса, который поддерживает консольные операции ввода-вывода данных.
    Связав класс
    Console с методом
    WriteLine()
    , вы тем самым сообщаете компилятору, что
    WriteLine()
    — член класса
    Console
    . Тот факт, что в C# для определения консольного вывода данных используется некоторый объект, является еще одним свидетельством объектно-ориентированной природы этого языка программирования.
    Обратите внимание на то, что инструкция, содержащая вызов метода
    WriteLine()
    , завершается точкой с запятой, как и рассмотренная выше инструкция программы using
    System
    . В C# точкой с запятой завершаются все инструкции. Если же вы встречаете строки программы, которые не оканчиваются точкой с запятой, значит, они попросту не являются инструкциями.
    Первая в программе закрывающая фигурная скобка (
    }
    ) завершает метод
    Main()
    , а вторая — определение класса
    Example
    И еще. В языке C# различаются прописные и строчные буквы. Игнорирование этого факта может вызвать серьезные проблемы. Например, если случайно вместо имени Main ввести имя main или вместо
    WriteLine ввести writeline
    , то рассмотренная ниже программа сразу же станет некорректной. Более того, хотя C#-компилятор компилирует классы, которые не содержат метода
    Main()
    , у него нет возможности выполнить их.
    Поэтому, даже если вы введете имя
    Main с опечаткой (
    main
    ), компилятор все равно скомпилирует программу. Но затем вы получите сообщение об ошибке, уведомляющее о том, что в файле
    Example.exe не определена точка входа.
    Обработка синтаксических ошибок
    Введите, скомпилируйте и выполните рассмотренную выше программу (если вы еще не сделали этого). При вводе в компьютер текста программы вручную очень легко сделать случайную опечатку. К счастью, при попытке скомпилировать некорректно введенную программу компилятор сообщит о наличии в ней синтаксической ошибки (ошибок). При этом C#-компилятор попытается найти какой-либо смысл в предоставленном ему исходном коде независимо от того, что вы ему “подсунули”. Поэтому ошибка, о которой
    “просигналил” компилятор, может не всегда отражать истинную причину проблемы.
    Например, если в предыдущей программе случайно опустить

    Глава 2. Обзор элементов языка C#
    41 открывающую фигурную скобку после имени метода
    Main()
    , компилятор IDE сгенерирует последовательность “обнаруженных” ошибок, показанную на рис 2.6.
    (аналогичный отчет об ошибках генерируется и в результате вызова компилятора командной строки csc
    )
    Рис. 2.6. Отчет об ошибках
    Очевидно, первое сообщение об ошибке неверно, поскольку пропущена не точка с запятой, а фигурная скобка. Следующие два сообщения вообще могут лишь сбить с толку
    Цель этих рассуждений — доказать, что если в программе присутствует синтаксическая ошибка, то не все сообщения компилятора следует принимать “за чистую монету” Они могут легко ввести в заблуждение. Чтобы найти ошибку, нужно при анализе сообщений, генерируемых компилятором, научиться “ясновидению”. Кроме того, делу может помочь просмотр нескольких последних строк кода, непосредственно предшествующих строке с “обнаруженной” ошибкой. Ведь иногда компилятор начинает
    “чуять недоброе” только через несколько строк после реального местоположения ошибки.
    Небольшая вариация на тему первой программы
    Несмотря на то что инструкцию using System; используют все программы в этой книге, в первой программе без нее можно обойтись.
    Однако не стоит забывать, что она предоставляет большое удобство для программиста.
    Причина же ее необязательности состоит в том, что в C# можно всегда полностью
    определить имя с использованием пространства имен, которому оно принадлежит.
    Например, программную строку
    Console.WriteLine("Простая C#-программа."); можно заменить следующей
    System.Console.WriteLine("Простая C#-программа.");
    Таким образом, первую программу можно переписать следующим образом
    // Эта версия не включает инструкцию using System. class Example {
    // Любая C#-программа начинается с вызова метода Main(). public static void Main() {
    //
    Здесь имя Console.WriteLine полностью определено.
    System.Console.WriteLine("Простая C#-программа. ");
    }
    }

    42
    Часть I. Язык C#
    Поскольку довольно утомительно указывать пространство имен
    System везде, где используется его член, большинство C#-программистов включают в начало программ инструкцию using System
    (эта участь постигла и все программы, представленные в этой книге). Однако важно понимать, что при необходимости можно полностью определить любое имя, явно указав пространство имен, которому оно принадлежит.
    Вторая простая программа
    При использовании любого языка программирования нет более важной инструкции, чем присваивание переменной значения. Переменная — это именованная область памяти, которой может быть присвоено определенное значение. Во время выполнения программы значение переменной может меняться. Другими словами, содержимое переменной не фиксировано, а изменяемо.
    Следующая программа создает две переменные с именами x
    и y
    // Эта программа демонстрирует работу с переменными. using System; class Example2 { public static void Main() { int x; // Здесь объявляется переменная. int y; // Здесь объявляется еще одна переменная. x = 100; // Здесь переменной x присваивается 100.
    Console.WriteLine("x содержит " + x); y = x / 2;
    Console.Write("y содержит x / 2: ");
    Console.WriteLine(y);
    }
    }
    При выполнении этой программы вы должны увидеть следующий результат: x содержит 100 y содержит x / 2: 50
    Что же нового в этой программе? Итак, инструкция int x; // Здесь объявляется переменная. объявляет переменную с именем x
    целочисленного типа. В C# все переменные должны быть объявлены до их использования. В объявлении переменной помимо ее имени необходимо указать, значения какого типа она может хранить. Тем самым объявляется тип
    переменной. В данном случае переменная x
    может хранить целочисленные значения, т.е. целые числа. В C# для объявления переменной целочисленного типа достаточно поставить перед ее именем ключевое слово int
    . Таким образом, инструкция int x;
    объявляет переменную x
    типа int
    Следующая строка программы объявляет вторую переменную с именем y
    int y; //Здесь объявляется еще одна переменная.
    Обратите внимание на то, что здесь используется тот же формат объявления, что и в предыдущей строке кода. Разница состоит лишь в именах объявляемых переменных.
    В общем случае, чтобы объявить переменную, необходимо использовать инструкцию следующего формата:

    Глава 2. Обзор элементов языка C#
    43
    тип
    имя_переменной
    ;
    Здесь с помощью элемента
    тип
    задается тип объявляемой переменной, а с помощью элемента
    имя_переменной
    — ее имя. Помимо типа int
    , C# поддерживает и другие типы данных.
    Следующая строка кода присваивает переменной x
    значение
    100
    x = 100; //Здесь переменной x присваивается 100.
    В C# оператор присваивания представляется одиночным знаком равенства (
    =
    ). Его действие заключается в копировании значения, расположенного справа от оператора, в переменную, указанную слева от него.
    Следующая строка кода выводит значение переменной x
    , предваряя его текстовой строкой “
    x содержит
    “.
    Console.WriteLine("x содержит " + x);
    В этой инструкции знак “плюс” означает не операцию сложения, а последовательное отображение заданной текстовой строки и значения переменной x
    . В общем случае, используя оператор “
    +
    ”, можно в одной инструкции вызова метода
    WriteLine()
    сформировать сцепление элементов в нужном количестве.
    Следующая строка кода присваивает переменной y
    значение переменной x
    , разделенное на 2. y = x / 2;
    При выполнении этой строки программы значение переменной x
    делится на
    2
    , а затем полученный результат сохраняется в переменной y
    . Таким образом, переменная y
    будет содержать значение
    50
    . Значение переменной x
    при этом не изменится. Подобно большинству языков программирования, C# поддерживает полный диапазон арифметических операторов, включая следующие:
    +
    Сложение
    -
    Вычитание
    *
    Умножение
    /
    Деление
    Рассмотрим две строки программы:
    Console.Write("y содержит x / 2: ");
    Console.WriteLine(y);
    Здесь сразу два новых момента. Во-первых, для отображения строки "
    y содержит x/2:
    " используется не уже знакомый нам метод
    WriteLine()
    , а встроенный метод
    Write()
    . B этом случае выводимая текстовая строка не сопровождается символом новой строки. Это означает, что выполнение очередной операции вывода данных будет начинаться на той же строке. Таким образом, метод
    Write()
    аналогичен методу
    WriteLine()
    , но с той лишь разницей, что после каждого вызова он не выводит символ новой строки. Во-вторых, обратите внимание на то, что в обращении к методу
    WriteLine()
    переменная y
    используется самостоятельно, т.е. без текстового сопровождения. Эта инструкция служит демонстрацией того, что как
    WriteLine()
    , так и
    Write()
    можно использовать для вывода значений любых встроенных C#-типов,
    Необходимо также отметить, что с помощью одной инструкции можно объявить сразу две или больше переменных. Для этого достаточно разделить их имена запятыми.
    Например, в рассмотренной программе переменные x
    и y
    можно было объявить следующим образом: int x, y; //Объявление обеих переменных в одной инструкции.

    44
    Часть I. Язык C#
    Другие типы данных
    В предыдущей программе мы использовали переменную типа int
    . Однако в переменной типа int можно хранить только целые числа. Следовательно, ее нельзя использовать для обработки дробной части числа. Например, в int
    -переменной может содержаться значение 18, но отнюдь не значение 18,3. К счастью, тип данных int
    — не единственный тип, определенный в C#. Для обработки чисел с дробной частью в C# предусмотрены два типа данных с плавающей точкой, float и double
    , которые представляют значения с обычной и удвоенной точностью, соответственно. (Тип double пользуется у программистов “повышенным спросом”.)
    Для объявления переменной типа double используйте инструкцию, подобную следующей: double result
    ;
    Здесь result
    - это имя переменной типа double
    . Поскольку переменная result имеет тип double
    , она может хранить такие значения, как 122,23, 0,034 или -19,0.
    Чтобы лучше понять различие между типами данных int и double
    , рассмотрим следующую программу:
    /*
    Эта программа иллюстрирует различие между типами int и double.
    */ using System; class Example3 { public static void Main() { int ivar; // Объявляем переменную типа int. double dvar; // Объявляем переменную типа double. ivar = 100; // Присваиваем переменной ivar
    // значение 100. dvar = 100.0;
    // Присваиваем переменной dvar
    // значение 100.0.
    Console.WriteLine(
    "Исходное значение переменной ivar: " + ivar);
    Console.WriteLine(
    "Исходное значение переменной dvar: " + dvar);
    Console.WriteLine();
    //
    Выводим пустую строку.
    //
    Теперь делим оба значения на 3. ivar = ivar / 3; dvar = dvar / 3.0;
    Console.WriteLine("ivar после деления: " + ivar);
    Console.WriteLine("dvar после деления: " + dvar);
    }
    }
    Вот как выглядит результат выполнения этой программы:
    Исходное значение переменной ivar: 100
    Исходное значение переменной dvar: 100

    Глава 2. Обзор элементов языка C#
    45 ivar после деления: 33 dvar после деления: 33.3333333333333
    Как видите, при делении переменной ivar на 3 выполняется операция целочисленного деления, результат которой равен 33, т.е. дробная часть отбрасывается. Но при делении переменной dvar на 3 дробная часть сохраняется.
    Итак, если нужно определить в программе значение с плавающей точкой, необходимо включить в его представление десятичную точку. Если этого не сделать, оно будет интерпретироваться как целое число. Например, в C# число
    100
    рассматривается как целое, а число
    100.0
    — как значение с плавающей точкой.
    Обратите внимание на то, что для вывода пустой строки достаточно вызвать метод
    WriteLine без аргументов.
    Тип данных с плавающей точкой обычно используется при работе с реальными значениями, т.е. когда необходимо учитывать дробную часть каждого числа. Например, следующая программа вычисляет площадь круга, используя для π значение 3,1416.
    // Вычисляем площадь круга. using System; class Circle { static void Main() { double radius; double area; radius = 10.0; area = radius * radius * 3.1416;
    Console.WriteLine("Площадь равна " + area);
    }
    }
    Результат выполнения-этой программы таков:
    Площадь равна 314.16
    Очевидно, что вычисление площади круга не может быть вычислено с удовлетворительным результатом без использования данных с плавающей точкой.
    Первое знакомство с инструкциями управления
    Инструкции внутри метода выполняются последовательно, можно сказать, сверху вниз. Но такой ход выполнения можно изменить с помощью различных инструкций управления, поддерживаемых в C#. Подробно инструкции управления будут рассмотрены ниже, а пока мы кратко познакомимся с двумя из них, поскольку они используются в примерах программ, приведенных в этом разделе.
    Инструкция if
    С помощью инструкции if можно организовать избирательное выполнение части программы. Действие инструкции if в C# во многом подобно действию одноименной инструкции в любом другом языке программирования. Что касается языков C, C++ и Java, то здесь налицо полная идентичность. Вот как выглядит простейшая форма записи этой инструкции: if(
    условие
    )
    инструкция
    ;

    46
    Часть I. Язык C#
    Здесь элемент
    условие
    представляет собой булево выражение (которое приводится к значению ИСТИНА или ЛОЖЬ), Заданная
    инструкция
    будет выполнена, если
    условие
    окажется истинным. В противном случае (если
    условие
    окажется ложным) заданная
    инструкция
    игнорируется. Рассмотрим следующий пример: if(10 < 11) Console.WriteLine("10 меньше 11");
    В данном случае число 10 действительно меньше 11, т.е. условное выражение истинно, поэтому метод
    WriteLine()
    будет вызван. Рассмотрим другой пример: if(10 < 9) Console.WriteLine("Этот текст выведен не будет.");
    Здесь же число 10 никак не меньше 9, поэтому вызов метода
    WriteLine()
    не произойдет.
    В C# определен полный комплект операторов отношения, которые можно использовать в условных выражениях. Вот их список:
    <
    Меньше
    <=
    Меньше или равно
    >
    Больше
    >=
    Больше или равно
    ==
    Равно
    !=
    Не равно
    Следующая программа иллюстрирует использование инструкции if
    // Демонстрация использования инструкции if. using System; class IfDemo { public static void Main() { int a, b, c; a = 2; b = 3; if(a < b) Console.WriteLine("а меньше b");
    //
    Следующая инструкция ничего не отобразит на экране. if(a == b) Console.WriteLine(
    "Этого текста никто не увидит.");
    Console.WriteLine(); c = a - b; // Переменная c содержит -1.
    Console.WriteLine("c содержит -1"); if(c >= 0) Console.WriteLine(
    "Значение c неотрицательно"); if(c < 0) Console.WriteLine("Значение c отрицательно");
    Console.WriteLine(); c = b - a; // Теперь переменная c содержит 1.
    Console.WriteLine("c содержит 1"); if(c >= 0) Console.WriteLine(
    "Значение c неотрицательно"); if(c < 0) Console.WriteLine("Значение c отрицательно");
    }
    }

    Глава 2. Обзор элементов языка C#
    47
    Результат выполнения этой программы имеет такой вид: а меньше b c содержит -1
    Значение c отрицательно c содержит 1
    Значение c неотрицательно
    Обратите внимание вот на что. В строке int a, b, c; объявляются сразу три переменных за счет использования списка элементов, разделенных запятой. Как упоминалось выше, две или больше переменных одинакового типа можно объявить в одной инструкции, отделив их имена запятыми.
    Цикл for
    Чтобы многократно выполнить последовательность программных инструкций, необходимо организовать цикл. В языке C# циклические конструкции представлены в богатом ассортименте. В этом разделе мы рассмотрим цикл for
    . Если вы знакомы с C, C++ или Java, то вам будет приятно узнать, что цикл for в C# работает точно так же, как в этих языках. Простейшая форма записи цикла for имеет следующий вид. for(
    инициализация
    ;
    условие
    ;
    итерация
    )
    инструкция
    ;
    В самой общей форме элемент
    инициализация
    устанавливает управляющую переменную цикла равной некоторому начальному значению. Элемент
    условие
    представляет собой булево выражение, в котором тестируется значение управляющей переменной цикла. Если результат этого тестирования истинен, цикл for выполняется еще раз, в противном случае его выполнение прекращается. Элемент
    итерация
    — это выражение, которое определяет, как изменяется значение управляющей переменной цикла после каждой итерации. Рассмотрим небольшую программу, в которой иллюстрируется цикл for
    // Демонстрация цикла for. using System; class ForDemo { public static void Main() { int count; for(count = 0; count < 5; count = count+1)
    Console.WriteLine("Это счет: " + count);
    Console.WriteLine("Готово!");
    }
    }
    Вот как выглядит результат выполнения этой программы:
    Это счет: 0
    Это счет: 1
    Это счет: 2
    Это счет: 3
    Это счет: 4
    Готово!

    48
    Часть I. Язык C#
    В этой программе управляющей переменной цикла является count
    . В выражении инициализации цикла for она устанавливается равной нулю. В начале каждой итерации
    (включая первую) выполняется проверка условия count < 5
    . Если результат этой проверки окажется истинным, выполнится инструкция вывода строки
    WriteLine()
    , а после нее — итерационное выражение цикла. Этот процесс будет продолжаться до тех пор, пока проверка условия не даст в результате значение ЛОЖЬ, после чего выполнение программы возобновится с инструкции, расположенной за циклом.
    Интересно отметить, что в C#-программах, написанных профессиональными программистами, редко можно встретить итерационное выражение цикла в том виде, в каком оно представлено в рассматриваемой программе. Другими словами, вряд ли вы увидите инструкции, подобные следующей: count = count + 1;
    Дело в том, что C# включает специальный оператор инкремента, который позволяет более эффективно выполнить операцию увеличения значения на единицу. Оператор инкремента обозначается двумя последовательными знаками “плюс” (
    ++
    ). С его помощью предыдущую инструкцию можно переписать следующим образом: count++;
    Следовательно, начало цикла for в предыдущей программе опытный программист оформил бы так: for(count = 0; count < 5; count++)
    Если вам захочется выполнить предыдущую программу, используя оператор инкремента, вы убедитесь, что результат останется прежним.
    В C# также предусмотрен оператор декремента (
    --
    ). Нетрудно догадаться, что этот оператор уменьшает значение операнда на единицу.
    Использование блоков кода
    Не менее важным, чем инструкции управления, элементом языка C# является
    программный блок. Программный блок представляет собой группирование двух или более инструкций. Такое группирование инструкций реализуется посредством их заключения между открывающей и закрывающей фигурными скобками. После создания блок кода становится логическим элементом программы, который можно использовать в любом ее месте, где может находиться одна инструкция. Например, блок может быть частью, if
    - или for
    -инструкций. Рассмотрим следующую if
    -инструкцию: if(w < h)
    { v = w * h; w = 0;
    }
    Здесь сравниваются значения переменных w
    и h
    , и если оказывается, что w < h
    , то будут выполнены обе инструкции внутри блока. Следовательно, две инструкции в блоке образуют логический элемент, в результате чего одна инструкция не может быть выполнена без выполнения другой. Важно то, что, если нужно логически связать две или более инструкций, это легко реализуется созданием программного блока. Именно благодаря блокам можно упростить код реализации многих алгоритмов и повысить эффективность их выполнения.
    Рассмотрим программу, в которой программный блок используется для предотвращения деления на нуль.
    // Демонстрация использования программного блока.

    Глава 2. Обзор элементов языка C#
    49 using System; class BlockDemo { public static void Main() { int i, j, d; i = 5; j = 10;
    //
    Эта if-инструкция управляет программным
    // блоком, а не одной инструкцией. if(i != 0) {
    Console.WriteLine("i не равно нулю"); d = j / i;
    Console.WriteLine("j
    / i равно " + d);
    }
    }
    }
    Результат выполнения этой программы имеет следующий вид: i не равно нулю j / i равно 2
    В этом случае if
    -инструкция управляет программным блоком, а не просто одной инструкцией. Если управляющее условие if
    -инструкции окажется истинным (а оно таким здесь и является), будут выполнены все три инструкции, составляющие этот блок.
    Проведите небольшой эксперимент. Замените в этой программе инструкцию i = 5; инструкцией i = 0; и сравните результат выполнения нового варианта программы со старым.
    А вот еще один пример. На этот раз программный блок используется для вычисления суммы чисел от 1 до 10 и их произведения.
    // Вычисляем сумму и произведение чисел от 1 до 10. using System; class ProdSum { static void Main() { int prod; int sum; int i; sum = 0; prod = 1; for(i=1; i <= 10; i++) { sum = sum + i; prod = prod * i;
    }
    Console.WriteLine("Сумма равна " + sum);
    Console.WriteLine("Произведение равно " + prod);
    }
    }
    В результате выполнения программы получаем следующее:

    50
    Часть I. Язык C#
    Сумма равна 55
    Произведение равно 3628800
    Здесь (благодаря блоку) в одном цикле вычисляется как сумма чисел, так и их произведение. Без этого средства языка пришлось бы использовать два отдельных for
    - цикла.
    И еще. Программные блоки не снижают динамику выполнения программ. Другими словами, наличие фигурных скобок (
    {
    и
    }
    ) не означает дополнительных затрат времени на выполнение программы. Наоборот, благодаря способности блоков кода упрощать программирование алгоритмов, повышается скорость и эффективность выполнения программ в целом.
    Использование точки с запятой и оформление
    текста программы
    В C# точка с запятой означает конец инструкции, т.е. каждая отдельная инструкция должна оканчиваться точкой с запятой.
    Как вы уже знаете, блок — это набор логически связанных инструкций, заключенный между открывающей и закрывающей фигурными скобками. Поскольку каждая из инструкций блока завершается точкой с запятой, то признаком завершения самого блока является закрывающая фигурная скобка (а не точка с запятой).
    C# не распознает конец строки как конец инструкции; признаком конца инструкции служит только точка с запятой, поэтому расположение инструкции в строке не имеет значения. Например, в C# следующий фрагмент кода x = y; y = y + 1;
    Console.WriteLine(x + " " + y); абсолютно идентичен представленному в виде одной строке. x = y; y = y + 1; Console.WriteLine(x + " " + y);
    Более того, различные элементы инструкции можно расположить на отдельных строках. Например, следующая запись инструкции абсолютно приемлема.
    Console.WriteLine("Это длинная текстовая строка" + x + y + z +
    "другие данные, подлежащие выводу");
    Подобное разбиение длинных программных строк часто позволяет сделать программу более читабельной.
    Использование отступов
    Глядя на текст предыдущих программ, вы, вероятно, заметили, что некоторые инструкции записаны с отступами от левого края. C# — это язык, допускающий свободную форму записи инструкций, т.е. не имеет значения, как расположены инструкции на строке относительно друг друга. Однако у программистов выработался определенный стиль оформления программ, который позволяет сделать программу максимально читабельной.
    Программы, представленные в этой книге, оформлены с соблюдением этого стиля, что рекомендуется делать и вам. Согласно этому стилю, после каждой открывающей фигурной скобки следует делать отступ (в виде нескольких пробелов), а после каждой закрывающей фигурной скобки — возвращаться назад (к предыдущему уровню отступа). Для некоторых инструкций рекомендуется делать дополнительный отступ, но об этом речь впереди.

    Глава 2. Обзор элементов языка C#
    51
    Ключевые слова C#
    В языке C# на данный момент определено 77 ключевых слов, которые перечислены в табл. 2.1. Эти ключевые слова (в сочетании с синтаксисом операторов и разделителей) образуют определение языка C#. Ключевые слова нельзя использовать в качестве имен переменных, классов или методов.
    Таблица 2.1. Ключевые слова C# abstract event new struct as explicit null switch base extern object this bool false operator throw break finally out true byte fixed override try case float params typeof catch for private uint char foreach protected ulong checked goto public unchecked class if readonly unsafe const implicit ref ushort continue in return using decimal int sbyte virtual default interface sealed volatile delegate internal short void do is sizeof while double lock stackalloc else long static enum namespace string
    Идентификаторы
    В C# идентификатор представляет собой имя, присвоенное методу, переменной или иному элементу, определенному пользователем. Идентификаторы могут состоять из одного или нескольких символов. Имена переменных должны начинаться с буквы или символа подчеркивания. Последующим символом может быть буква, цифра и символ подчеркивания. Символ подчеркивания можно использовать для улучшения читабельности имени переменной, например line_count
    . В C# прописные и строчные буквы воспринимаются как различные символы, т.е. myvar и
    MyVar
    — это разные имена. Вот несколько примеров допустимых идентификаторов.
    Test x у2 MaxLoad up _top my_var sample23
    Помните, что идентификатор не должен начинаться с цифры. Например,
    12х
    — недопустимый идентификатор. Конечно, вы вольны называть переменные и другие программные элементы по своему усмотрению, но обычно идентификатор отражает назначение или смысловую характеристику элемента, которому он принадлежит.

    52
    Часть I. Язык C#
    Несмотря на то что в C# нельзя использовать ключевые слова в качестве идентификаторов, любое ключевое слово можно “превратить” в допустимый идентификатор, предварив его символом “
    @
    ”. Например, идентификатор
    @fоr вполне пригоден для употребления в качестве допустимого C#-имени. Интересно, что в этом случае идентификатором все-таки является слово for
    , а символ
    @
    попросту игнорируется.
    Теперь самое время рассмотреть программу, в которой используется
    @
    -идентификатор.
    // Демонстрируем использование @-идентификатора. using System; class IdTest { static void Main() { int @if; // Используем if в качестве идентификатора. for(@if = 0; @if < 10; @if++)
    Console.WriteLine("@if равно " + @if);
    }
    }
    Результат выполнения этой программы доказывает, что
    @if действительно интерпретируется как идентификатор.
    @if равно 0
    @if равно 1
    @if равно 2
    @if равно 3
    @if равно 4
    @if равно 5
    @if равно 6
    @if равно 7
    @if равно 8
    @if равно 9
    Однако (за исключением специальных случаев) использование ключевых слов в качестве
    @
    -идентификаторов не рекомендуется. Кроме того, символ
    @
    может стоять в начале любого идентификатора (а не только созданного из ключевого слова), но это также не считается хорошим стилем программирования.
    Библиотеки классов C#
    В примерах программ, представленных в этой главе, использовано два встроенных
    C#-метода —
    WriteLine()
    и
    Write()
    . Как упоминалось выше, эти методы — члены класса Console, который является частью пространства имен
    System
    , определенного в библиотеках классов среды .NET Framework. Вы уже знаете, что C#-среда опирается на библиотеки классов среды .NET Framework, что позволяет ей обеспечить поддержку операций ввода-вывода, обработку строк, сетевые возможности и графические интерфейсы пользователя (GUIs). Таким образом, C# в целом — это объединение самого языка C# (его языковых элементов) и классов .NET-стандарта. Как будет показано ниже, библиотеки классов существенно повышают функциональность C#-программы. Чтобы стать профессиональным C#-программистом, важно научиться эффективно использовать эти стандартные классы. В части I мы познакомимся с элементами библиотечных классов .NET- стандарта, а детали .NET-библиотеки описаны в части II.

    Полный справочник по
    1   2   3   4   5   6   7   8   9   ...   52


    написать администратору сайта