→ Пошук по сайту       Увійти / Зареєструватися
Знання Мова програмування C#

Основи С#

Перш ніж перейти безпосередньо до дослідження конструктивних особливостей мови програмування C #, розглянемо хід його розвитку.

Історія основної гілки мов програмування, яка призвела до появи C #, сходить до 60-х років, а саме, до часу виникнення мови B. Останній є типовим представником ранніх імперативних мов програмування. Мова B була придумана у 1963 році творчим колективом розробників, основним творцем мови прийнято вважати К. Томпсона з Технологічного інституту Массачусетсу (Ken Thompson, MIT). Основною метою розробки мови була реалізація операційної системи UNIX. Вже існувала мова PL / I, що застосовувалася у той час для мейнфреймів виробництва компанії IBM, була досить громіздкою і менше підходила для поставленої задачі, ніж нове, оригінальне рішення вчених-практиків.

Наступним кроком в "алфавіті" мов програмування, провідному до мови C #, стала мова C, яка була винайдена на основі мови B в 1972 році. Авторами нової мови програмування стали К. Томпсон і Д. Рітчі (Dennis Ritchie), які працювали в дослідницькій лабораторії компанії AT & T (AT & T Bell Telephone Laboratories). У варіанті C мови B розширився за рахунок явного використання типів, структур і ряду нових операцій. Подальший розвиток мови відбувалося в тій же організації. І знову приблизно через 10 років, в 1984 році, Б. Страуструп (Bjarne Stroustrup, Bell Labs) виступив з проектом мови С + + - ООП-розширення мови C, в якому вводиться поняття класу як об'єкта даних.

Зауважимо, що назва C + + для нової мови запропонував Р. Маскітті (Rics Mascitti, Bell Labs).

Нарешті, вже в 2000 році, тобто більш ніж через 15 років, корпорація Microsoft випустила у світ C + + нового покоління під назвою C # ("Сі шарп"), основним постулатом якого є вислів: "будь-яка сутність є об'єкт". Мова заснована на строгій компонентній архітектурі і реалізує передові механізми забезпечення безпеки коду.

Як вже зазначалося в ході лекції, мова програмування C # об'єднала кращі риси цілого ряду попередників. Крім згаданої раніше гілки мов BC-C + +, необхідно вказати ще кілька знакових для нашого часу мов програмування, а саме, Java і Visual Basic.

Незважаючи на дуже серйозні розбіжності між компонентною об'єктною моделлю COM (основного стандарту Microsoft для компонентного проектування та реалізації програмного забезпечення) і моделлю Java Beans, базовим стандартом Sun Microsystems для компонента (залежної від мови реалізації), мова програмування C # має досить багато спільного з мовою Java . Природно, чимало рис мова програмування C # успадкував і від свого попередника, створеного корпорацією Microsoft, мови Visual Basic.

Як вже зазначалося, мова програмування C # заснований на строгій компонентній архітектурі і реалізує передові механізми забезпечення безпеки коду.

Перелічимо найбільш характерні риси подібності мов програмування C # і Java. Перш за все, обидві мови належать до категорії об'єктно-орієнтованих і припускають єдиність наслідування. Іншими важливими особливостями, які зближують мови програмування C # і Java, є механізми інтерфейсів, обробки виняткових ситуацій, а також процесів або "ниток" (threads). "Збірка сміття" і простору імен реалізовані у цих двох мовах подібним чином. Обидві мови програмування характеризуються сильною (суворою) типізацією та динамічним завантаженням коду при виконанні програми.

Від свого прямого попередника, мови програмування C + +, мовою C # успадковані наступні механізми: "перевантажені" оператори, небезпечні арифметичні операції з плаваючою точкою, а також ряд інших особливостей синтаксису. Але незважаючи на те, що цілий ряд конструктивних синтаксичних механізмів і особливостей реалізації успадкований мовою програмування C # від прабатьків (C + +, Visual Basic і Java), можливості цього нового мови програмування не обмежуються сумою можливостей його історичних попередників.

Таблиця 15.1. Основні можливості C#

Подібно мовам Java, C++ и VB, але являється компонентно-орієнтованим і більш безпечним.
Додано ряд нових рис (делегати, індексатори, механізм (un)boxing и т.д.)

   Схожість з Java

   Схожість з С++

  • компонентно-орієнтованим
  • інтерфейси
  • виключення
  • нитки (threads)
  • простір імен
  • сильна (сувора) типізація
  • збір сміття
  • відображення (reflection)
  • динамічна загрузка коду
  • "перевантажені" оператори
  • небезпечні арифметичні операції з плаваючою точкою
  • деякі особливості синтакиса

До числа принципово важливих рішень, які реалізовані корпорацією Microsoft у мові програмування C #, можна віднести наступні:

  • компонентно-орієнтований підхід до програмування (який характерний і для ідеології Microsoft. NET в цілому);
  • властивості як засіб інкапсуляції даних (характерно також в цілому для ООП);
  • обробка подій (маються розширення, в тому числі в частині обробки виключень, зокрема, оператор try);
  • обробка подій (маються розширення, в тому числі в частині обробки виключень, зокрема, оператор try);
  • делегати (delegate - розвиток покажчика на функцію в мовах C і C);
  • індексатори (indexer - оператори індексу для звернення до елементів класу-контейнера);
  • перевантажені оператори (розвиток ООП);
  • оператор foreach (обробка всіх елементів класів-колекцій, аналог Visual Basic);
  • механізми boxing і unboxing для перетворення типів;
  • атрибути (засіб оперування метаданими в COM-моделі);
  • прямокутні масиви (набір елементів з доступом за номером індексу і однаковою кількістю стовпців і рядків).

 Структура програми на мові C#
Рис. 15.1. Структура програми на мові C #.

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

Перш за все, розглянемо узагальнену структуру програми на мові програмування C #. Уявімо структуру програми на прикладі (див. ріс.15.1).

Зауважимо, що програма на C # може складатися як з одного, так і з декількох файлів, що містять вихідний текст на мові програмування C #. Кожен такий файл має розширення. CS (у нашому прикладі файли названі FileName1.cs, FileName2.cs і FileName3.cs).

Будь-який файл з вихідним текстом на мові програмування C # може як містити простор імен, так і не містити їх (у нашому прикладі файл FileName2.cs включає три простори імен, A, B і C, а FileName1.cs і FileName3.cs не містять просторів імен).

Нарешті, кожне простір імен може як містити опис класів (одного або декількох), так і не містити (у нашому прикладі простір імен B містить три описи трьох класів (X, Y і Z), а простори імен А і С не містять жодного опису класів).

Раніше в ході лекцій вже обговорювалися механізми boxing і unboxing, реалізовані в різних середовищах розробки програмного забезпечення Microsoft. NET. Нагадаємо, що ці механізми використовуються для перетворення типів виразів мов програмування з посилальних в Типи-значення, і назад.

Таблиця 15.2. Зіставлення посилальних типів и типів-значень.

 

Типи-значення

Посилальні типи

Змінна має

значення

посилання на значення

Змінна зберігає

в стеку

в кучі

Значення по замовченню

0, false, ‘\0’

null

Оператор присвоєння

копіює значення

копіює посилання

Приклад

int i = 25;

int j = i;

i [25]

j [25]

string s = "John"

string sl = s;

s [ ]

[John]

sl [ ]

 

Розглянемо більш детально реалізацію двох основних сімейств типів даних, а саме, посилальних типів і типів-значень, стосовно мови програмування C #. Для визначеності візьмемо випадок одного з найпростіших об'єктів мови програмування C #, а саме, змінної.

Відповідно з назвами, змінна в разі застосування типів-значень містить власне значення, а при використанні посилальних типів - не саме значення, а лише посилання (покажчик) на нього.

Місцем зберігання змінної, визначеної як тип-значення, є стек, а визначеної як контрольний тип - "купа" (останнє необхідно для динамічного виділення та звільнення пам'яті для зберігання змінної довільним чином).

Значенням, яким мінливо ініціалізується за замовчуванням (необхідність виконання цієї вимоги диктується ідеологією безпеки Microsoft. NET) у разі визначення вигляді типу-значення є 0 (для цілого або дійсного типу даних), false (для логічного типу даних), '\ 0' ( для строкового типу даних), а у разі визначення за допомогою посилального типу - значення порожнього посилання null.

При виконанні оператора присвоювання у разі змінної-значення копіюється значення, а у разі змінної-посилання - посилання.

Наведений приклад ілюструє розходження в реалізації типів-посилань і значень (див. табл. 15.2).

Перейдемодо більш докладногоопису основнихтипів, що входятьдо складуCommon Type System(CTS) Microsoft. NET. Прицьомуприкладнедослідження мовпрограмуваннязробимоу формі зіставлення відображень фрагментів систем типізації мов програмування SML і C# в систему типів CTS.

Таблиця 15.3. Зіставлення відображень типів мов SML и C# в систему типів .NET.

C#

CTS (.NET)

SML

Диапазон

sbyte

System.SByte

---

-128..127

byte

System.Byte

byte

0..255

short

System.Int16

int

-32768..32767

ushort

System.UInt16

word

0..65535

long

System.Int64

---

-263..263-1

float

System.Single

real

+1.5E-45..+3.4E+38 (32 Bit)

double

System.Double

---

+5E-324..+1.7E+308 (64 Bit)

decimal

System.Decimal

---

+1E-28..+7.9E+28 (128 Bit)

bool

System.Boolean

bool

true, false

char

System.Char

char

Символ (в коді unicode)

Навіть з попереднього аналізу таблиці видно, що система типізації мови програмування С # значно багатша у порівнянні з мовою програмування SML. Можна помітити, що всякому типу мови програмування SML відповідає певний тип мови програмування С #, і їх назви часто співпадають або бувають схожими.

Нарешті, відзначимо, що всі без винятку види обох мов програмування однозначно відображаються в систему типізації Microsoft. NET, верхнім ієрархічним елементом якої є простір імен System.

Крім поняття змінної, яке вже розглядалося раніше у зв'язку з типами-значеннями і посилальними типами, цікаво провести дослідження об'єктів-констант в мові програмування C #.

Нагадаємо, що константні об'єкти в комбінаторній логіці можна моделювати за допомогою комбінатора-канцелятора К з характеристикою Kxy = x.

Розглянемо ряд прикладів опису констант за допомогою оператора перерахування (зауважимо, що вживаний в C # спосіб опису констант початку орієнтований на написання безпечного коду, оскільки містить обов'язкову ініціалізацію).

Оператор перерахування enum мови C # представляє собою список пойменованих констант. Опис виробляється безпосередньо в просторі імен з областю видимості, яку необхідно забезпечити для константи:

enum Color {red, blue, green}
enum Access {personal=1, group=2, all=4}
enum Access1 : byte {personal=1, group=2, all=4} 

Приклад використання константи після її опису має наступний вигляд:

Color c = Color.blue;   

Зауважимо, що для перелічуваних констант має бути зазначено повне ім'я:

Access a = Access.personal | Access.group
   if((Access.personal & a) != 0)      
       Console.WriteLine("access granted";

Подібно до мови програмування SML в мові C # реалізована можливість визначення типу для того чи іншого мовного об'єкта. Для реалізації такої можливості використовується оператор typeof, який для будь-якого заданого типу повертає дескриптор цього типу.

Зауважимо, що дескриптор типу для об'єкта o повертається операцією o.GetType (). Розглянемо приклад, який ілюструє використання оператора

typeof:
   Type t = typeof(int);
   Console.WriteLine(t.Name); 

При виконанні даного прикладу тип розглянутого виразу буде визначений системою як Int32, що цілком відповідає даним з порівняльної таблиці відображення типів мовних об'єктів C # і SML в систему типізації CTS Microsoft. NET.

Ще однією практично важливою конструкцією C #, що оперує типами, є оператор sizeof, який повертає розмір елемента даного типу (в байтах). Даний оператор застосовується лише до типів-значень і використовується лише в блоках небезпечного коду (тому що розмір структур може змінюватися в залежності від середовища реалізації); необхідна компіляція коду командою csc / unsafe xxx.cs.

Наведемо приклад використання оператора sizeof (зауважимо, що блоки небезпечного C #-коду виділяються за допомогою ключового слова unsafe):

unsafe
{
        Console.WriteLine(sizeof(int));
        Console.WriteLine(sizeof(MyEnumType));
        Console.WriteLine(sizeof(MyStructType));
} 

Одним з найважливіших видів основних об'єктів мови програмування C # є структури (аналоги структур є і в мові SML; в мовах функціонального програмування з примітивною системою типізації аналогами структур можуть служити списки).

Розглянемо приклад опису структури Point, що моделює точку на площині:

struct Point
{
       public int x, y;
       public Point (int x, int y)
       {
               this.x = x;
               this.y = y;
       }
       public void MoveTo (int a,int b)
       {
              x=a;
              y=b;
       }
}

Зауважимо, що координати точки x, y (у простому випадку цілочисельні), які використовуються для визначення її положення, є атрибутами об'єкта або полями структури. Операція Point є функцією ініціалізації об'єкту і називається конструктором. Зверніть увагу, що успадкований від C + + покажчик this являє собою посилання на поточний об'єкт. Нарешті, операція (або, інакше, метод) MoveTo змінює поточний місце розташування точки на пару цілочисельних координат (a, b). Для використання об'єкта-структури необхідно проініціалізувати об'єкт-значення в стеку допомогою конструктора. Потім можна викликати метод MoveTo: Point

p = new Point(3, 4);
p.MoveTo(10, 20); 

Ми познайомилися з одним із основних видів об'єктів мови програмування C #, а саме, зі структурами.

У попередньому прикладі фрагмента програми на C # двічі фігурував ідентифікатор Point. У зв'язку з цим доречно згадати про проблему колізій змінних і можливі шляхи її подолання (в попередній частині курсу для вирішення цього завдання використовувався формалізм, відомий під назвою чисел де Брейна). У мові програмування SML змінні можуть бути описані або глобально (цей опис поширюється на весь текст програми), або локально в тілі функції (це опис поширюється на весь текст функції).

У мові програмування C #, де об'єкти мають істотно більш складну структуру, вводиться поняття області опису, під якою розуміють фрагмент програми, до якого відноситься даний опис.

  • Об'єкти мови програмування C # можуть бути описані:
  • В просторі імен (класи, інтерфейси, структури, перерахування, делегати);
  • В класі, інтерфейсі, структурі (поля, методи, властивості, події, індексатори);
  • В перерахуванні (перераховуються константи);
  • В блоці (локальні змінні).

При цьому беруться такі контекстні умови.

По-перше, неприпустимий дворазовий опис в межах даної області опису. По-друге, послідовність описів є довільною. Виняток становлять локальні змінні, які необхідно описати до першого використання.

Крім того, приймаються такі умови про області видимості.

По-перше, будь-який ідентифікатор видно лише зі своєї області опису. По-друге, область видимості можна змінити за допомогою модифікаторів (private, protected).

У процесі вивчення структури програми на мові C # неодноразово вживався термін "простір імен". У силу існування більш значущих понять об'єктно-орієнтованого підходу до програмування в цілому та мови програмування C # зокрема, наводилося лише загальний опис даного терміну. Розглянемо простір імен мови програмування C # більш докладно.

Розглянемо два файли X.cs і Y.cs, що містять вихідні тексти програм на мові C #.

Зміст файлу X.cs:

namespace A
{
        ... class C ...
        ... interface I...
        ... struct S...
        ... enum e ...
        ... delegate d ...
        namespace B
        {
           // повне ім’я: A.B   
           ..
        }
}

namespace A 
{
        ...
        namespace B
        {      
           ...
        }

        namespace C
        {
           ...
        }
}

Зауважимо, що у файлі X.cs містяться описи просторів імен A і B, а у файлі Y.cs - A, B і C, причому в обох випадках наступний простір імен вкладений в A. При зверненні до вкладеного простору імен потрібно вказувати його повне ім'я, наприклад AB

Необхідно відзначити, що простір імен з різних файлів, що мають один і той же ідентифікатор, становлять єдину область опису. Зауважимо також, що вкладені простори імен складають власну (окрему) область опису.

Незважаючи на те, що мова програмування C # реалізує об'єктно-орієнтований підхід до програмування, цілий ряд характерних особливостей успадкований їм ще від ранніх процедурних прабатьків, передусім, мови C.

Однією з рис, успадкованих C # від мови програмування C, є блок операторів - послідовність операторів, розділених символами ";", обмежена фігурними дужками "{" і "}".

Аналогом оператора блоку в мовах функціонального програмування є функція.

У мові програмування С # виділяють різні види блоків, які можна проілюструвати таким прикладом:

void foo (int x)
{
               // блок методів       
               ... локальні змінні ...

               { 
                // вкладений блок
                ... локальні змінні ...
               }       

               for (int i = 0; ...)
               {

                  // блок структурованих              

                  // операторів

                   ... локальні змінні..           
               }

} 

Як видно з прикладу, блоки об'єднують (структуровані) оператори і методи. Допускається використання блоків, вкладених один в іншій. Для зручності читання тексту програми глибину вкладеності блоку краще візуалізувати за допомогою табуляції.

Розглянемо докладніше особливості опису локальних змінних у мові програмування C # на наступному прикладі програми:

void foo(int a)

{
        int b;
        if (...)
        {
            int b;
            // помилка: змінна b вже
            // описана в другому блоці
            int c;
            // поки опис коректний,
            // але ...
            int d;
            ...
       }
       else
       {
            int a;
            // помилка: змінна а вже
            // описана в зовнішньому блоці
            int d;
            // конфліктів з змінной d
            // х попереднього блоку нема
      }

      for (int i=0;...)
      {
            ...
      }
      for (int i=0;...)
      {
            ...
      }

      // фрагмент коректний: нема
      // конфліктів з змінною
      // i з попереднього циклу
      int c;
      // помилка: c вже описана в
      // даному просторі імен
} 

Розглянемо функцію foo з одним цілочисловим аргументом a, яка не повертає значення.

 Як видно з цього прикладу, колізії описів змінних виникають у випадках множинного опису всередині одного і того ж блоку або простору імен.

Зауважимо принагідно, що умовний оператор if ... else мови C # вельми схожий з подібним оператором мови SML, а оператор for є оператором циклу.

Розглянемо більш складний приклад використання просторів імен у мові програмування C #.

Нехай програмний проект на мові програмування C # містить три файли з описами структур даних, оформленими у вигляді окремих просторів імен:

Color.cs
        namespace Util
        {
               public enum Color
               {
                   ...
               }
        }

Figures.cs
        namespace Util.Figures
        {
               public class Rect
               {

                   ...
               }
               public class Circle
               {
                   ...
               }
       }

Triangle.cs
        namespace Util.Figures
        {
               public class Triangle
               {
                   ...
               }
        } 

У даному випадку при використанні повного імені простору імен (Util.Figures) можливо обійтися без конкретизації класів (Rect), описаних всередині цього простору імен. Однак у разі звернення до класів поза даного простору імен необхідно використовувати повне кваліфікаційне ім'я об'єкта (Util.Color):

using Util.Figures;
        class Test
        {
               Rect r;
               // без вказівника повного
               // імені так як використовуємо
               // (Util.Figures)
               Triangle t;
               Util.Color c;
               // з вказуванням
               // повного імені
        } 

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

Перш за все, необхідно відзначити, що мова програмування C # претендує на справжню об'єктну орієнтованість (а всяка мовна сутність претендує на те, щоб бути об'єктом).

Крім того, мова програмування C # покликана практично реалізувати компонентно-орієнтований підхід до програмування, який спричиняє меншу машинно-архітектурну залежності результуючого програмного коду, більш гнучку, переносимість та легкість повторного використання (фрагментів) програм.

Принципово важливою відмінністю від попередників є початкова орієнтація на безпеку коду (що особливо помітно в порівнянні з мовами C і C + +).

Уніфікована, максимально близька за масштабом і гнучкістю до Common Type System, прийнятої в Microsoft. NET, система типізації є важливою перевагою мови C #.

Розширена підтримка подієво-орієнтованого програмування вигідно відрізняє мову програмування C # від цілого ряду попередників.

Мова програмування C # є "рідним" для створення додатків в середовищі Microsoft. NET, оскільки найбільш тісно і ефективно інтегрований з нею.

Об'єднання кращих ідей сучасних мов програмування (Java, C + +, Visual Basic і ін) робить мову C # не просто сумою їх достоїнств, а мовою програмування нового покоління.

Незважаючи на значну кількість принципових переваг порівняно з існуючими аналогами, мова програмування C # не позбавлений і окремих недоліків, які, мабуть, носять суб'єктивний, локальний, тимчасовий характер.

Перш за все, необхідно відзначити ту обставину, що мова програмування C # має досить складний синтаксис (можна стверджувати, що приблизно 75% його синтаксичних можливостей аналогічні мови програмування Java, 10% подібні до мови програмування C + +, а 5% - запозичені з мови програмування Visual Basic) . Обсяг дійсно свіжих концептуальних ідей в мові C # відносно невисокий (на думку деяких дослідників, він, складає близько 10% від загального обсягу конструкцій мови).

Твердження, що мова програмування C # є чисто об'єктним, припускає неоднозначну інтерпретацію. Так, наприклад, професор K. Гуткнехт (K. Gutknecht) з інституту ETH (м. Цюріх, Швейцарія) запропонував альтернативну (так звану "активну") об'єктну модель для розробленого ним мови програмування Zonnon.

На сьогодні компілятор і середовище розробки програмного забезпечення, що підтримують мову C #, мають відносно невисокою продуктивністю (тобто код програми на мові C # компілюється і виконується приблизно в 100 разів повільніше, ніж той самий код на мові C). Справедливості заради треба відзначити, що продуктивність програм на C # цілком порівнянна з тим же показником для мови Java.

Поки програми, написані на мові C #, не можуть функціонувати під управлінням альтернативних операційних систем (ведуться роботи із забезпечення сумісності з операційними системами Linux і FreeBSD сімейства UNIX).

загрузка...
Сторінки, близькі за змістом