Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Структури




 

Структура - тип даних, аналогічний класу, але ряд важливих відмінностей, що має, від нього:

· структура є значущою, а не посилальним типом даних, тобто екземпляр структури зберігає значення своїх елементів, а не посилання на них, і розташовується в стеку, а не в хіпові;

· структура не може брати участь в ієрархіях спадкоємства, вона може реалізовувати тільки інтерфейси;

· у структурі заборонено визначати конструктор за умовчанням, оскільки він визначений неявно і привласнює всім її елементам значення за умовчанням (нулі відповідного типу);

· у структурі заборонено визначати деструктори.

Строго кажучи, будь-який значущий тип С# є структурним.

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

З іншого боку, передача структури в метод за значенням вимагає і додаткового часу, і додаткової пам'яті.

 

Синтаксис структури:

 

[атрибути ] [специфікатори] struct ім'я_ структури [: інтерфейси ] тіло _структури

Специфікатори структури мають такий же сенс, як і для класу. У специфікаторів доступу допускаються тільки public, internal і private (останній - тільки для вкладених структур).

Інтерфейси, що реалізовуються структурою, перераховуються через кому. Тіло структури може складатися з констант, полів, методів, властивостей, подій, індексаторів, операцій, конструкторів і вкладених типів. Правила їх опису і використання аналогічні відповідним елементам класів, за виключенням деяких відмінностей, витікаючих із згаданих раніше:

· оскільки структури не можуть брати участь в ієрархіях, для їх елементів не можуть використовуватися специфікатори protected і protected internal;

· структури не можуть бути абстрактними (abstract), до того ж за умовчанням вони безплідні (sealed);

· методи структур не можуть бути абстрактними і віртуальними;

· перевизначатися (тобто описуватися із специфікатором override) можуть тільки методи, успадковані від базового класу object;

· параметр this інтерпретується як значення, тому його можна використовувати для посилань, але не для привласнення;

· при описі структури не можна задавати значення полів за умовчанням - це буде зроблено в конструкторі за умовчанням, створюваному автоматично (конструктор привласнює значущим полям структури нулі, а посилальним - значення null).

У лістингу 9.9 приведений приклад опису структури, що представляє комплексне число. Для економії місця зі всіх операцій приведений тільки опис складання. Зверніть увагу на перевантажений метод ToString: він дозволяє виводити екземпляри структури на консоль, оскільки неявно викликається в методі Console.WriteLine. Використані в методі специфікатори формату описані в додатку.

Лістинг 9.9. Приклад структури

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace examp63

{

struct Complex

{

public double re, im;

public Complex(double re_, double im_)

{

re = re_; im = im_; // можна використовувати this.re, this.im

}

public static Complex operator + (Complex a, Complex b)

{

return new Complex(a.re + b.re, a.im + b.im);

}

 

public override string ToString()

{

return (string.Format("({0,2:0.##};{1,2:0.##})", re, im));

}

}

 

class Classl

{

static void Main()

{

Complex a = new Complex(1.2345, 5.6);

Console.WriteLine("а = " + a);

Complex b;

b.re = 10; b.im = 1;

Console.WriteLine("b = " + b);

Complex с = new Complex();

Console.WriteLine("c = " + с);

с = a + b;

Console.WriteLine("с = " + с);

}

}

}

 

Результат роботи програми:

а = (1.23; 5.6)

b = (10; 1)

с = (0; 0)

с = (11.23;6.6)

 

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

Привласнення структур має, що природно, значущу семантику, тобто при привласненні створюється копія значень полів. Те ж саме відбувається і при передачі структур як параметрів за значенням. Для економії ресурсів ніщо не заважає передавати структури в методи по посиланню за допомогою ключових слів ref або out.

Особливо значний виграш в ефективності можна отримати, використовуючи масиви структур замість масивів класів. Наприклад, для масиву з 100 екземплярів класу створюється 101 об'єкт, а для масиву структур - один об'єкт. Приклад роботи з масивом структур, описаних в попередньому лістингу:

 

Complex [] mas = new Complex[4];

for (int i = 0; i < 4; ++i)

mas[i].re = i;

mas[i].im = 2*i;

foreach (Complex elem in mas) Console.WriteLine(elem);

 

Якщо помістити цей фрагмент замість тіла методу Main в лістингу 9.9, отримаємо наступний результат:

 

(0 0)

(1 2)

(2 4)

(3 6)

 

9.7. Перелічення

При написанні програм часто виникає потреба визначити декілька зв'язаних між собою іменованих констант, при цьому їх конкретні значення можуть бути не важливі. Для цього зручно скористатися переліченим типом даних, всі можливі значення якого задаються списком цілочисельних констант, наприклад:

enum Menu { Read, Write, Append, Exit }

enum Веселка { Червоний, Оранжевий, Жовтий, Зелений, Синій, Фіолетовий }

Для кожної константи задається її символічне ім'я. За умовчанням константам привласнюються послідовні значення типу int, починаючи з 0, але можна задати і власні значення, наприклад:

enum Nums { two = 2, three, four, ten = 10, eleven, fifty = ten + 40 };

Константам three і four привласнюються значення 3 і 4, константі eleven - 11. Імена констант усередині кожного перелічення мають бути унікальними, а значення можуть бути різними.

Перевага перелічення перед описом іменованих констант полягає в тому, що зв'язані константи наочніше; крім того, компілятор виконує перевірку типів, а інтегроване середовище розробки підказує можливі значення констант, виводячи їх список.

 

Синтаксис перелічення:

 

[атрибути ] [специфікатори ] enum ім'я _ перелічення [: базовий_тип ] тіло _ перелічення [; ]

 

Специфікатори перелічення мають такий же сенс, як і для класу, причому допускаються тільки специфікатори new, public, protected, internal і private.

Базовий тип - це тип елементів, з яких побудовано перелічення. За умовчанням використовується тип int, але можна задати тип і явним чином, вибравши його серед цілочисельних типів (окрім char), а саме: byte, sbyte, short, ushort, int, uint, long і ulong. Необхідність в цьому виникає, коли значення констант неможливо або незручно представляти за допомогою типу int.

Тіло перелічення складається з імен констант, кожною з яких може бути привласнене значення. Якщо значення не вказане, воно обчислюється збільшенням одиниці до значення попередньої константи. Константи за умовчанням мають специфікатор доступу public.

Перелічення часто використовуються як вкладені типи, ідентифікуючи значення з якого-небудь обмеженого набору. Приклад такого перелічення приведений в лістингу 9.10.

 

 

Лістинг 9.10. Приклад перелічення

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace examp64

{

struct Боец

{

public enum Воинское_Звание

{ Рядовой, Сержант, Лейтенант, Майор, Полковник, Генерал }

 

public string Фамилия;

public Воинское_Звание Звание;

}

 

class Program

{

static void Main(string[] args)

{

Боец x;

x.Фамилия = " Иванов ";

x.Звание = Боец.Воинское_Звание.Сержант;

Console.WriteLine(x.Звание + " " + x.Фамилия);

}

}

}

Результат роботи програми: Сержант Іванов

Перелічення зручно використовувати для представлення бітових прапорів, наприклад:

 

enum Flags: byte

{

b0, b1. b2, b3 = 0x04, b4 = 0x08, b5 = 0x10, b6 = 0x20, b7 = 0x40

}

 

9.7.1 Операції з переліченнями

Із змінними переліченого типу можна виконувати арифметичні операції (+, - ++, --), логічні порозрядні операції (*, &, |, ~), порівнювати їх за допомогою операцій відношення (<, < =, >, >= = =,! =) і отримувати розмір в байтах (sizeof).

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

 

Приклад:

Flags а = Flags.b2 | Flags.b4;

Console.WriteLine("а = {0} {0,2:Х}", а);

++а;

Console.WriteLine("а = {0} {0.2:X}", а);

int х = (int) а;

Console.WriteLine("x = {0} {0.2:X}", x);

Flags b = (Flags) 65;

Console.WriteLine("b = {0} {0.2:X}", b);

Результат роботи цього фрагмента програми ({0,2:х} позначає шістнадцятирічний формат виведення):

 

a = 10 0A

a = 11 0B

x = 11 B

b = 65 41

 

Інший приклад використання операцій з переліченнями приведений в лістингу 9.11.

 

Лістинг 9.11. Операції з переліченнями

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace examp64

{

struct Боец

{

public enum Воинское_Звание

{ Рядовой, Сержант, Лейтенант, Майор, Полковник, Генерал }

public string Фамилия;

public Воинское_Звание Звание;

}

 

class Program

{

static void Main(string[] args)

{

Боец x;

x.Фамилия = " Иванов ";

x.Звание = Боец.Воинское_Звание.Сержант;

for (int i = 1976; i < 2006; i += 5)

{

if (x.Звание < Боец.Воинское_Звание.Генерал) ++x.Звание;

Console.WriteLine("Рік: {0} {1} {2}", i, x.Звание, x.Фамилия);

}

}

}

}

 

Результат роботи програми:

Рік 1976 Лейтенант Иванов

Рік 1981 Майор Иванов

Рік 1986 Полковник Иванов

Рік 1991 Генерал Иванов

Рік 1996 Генерал Иванов

Рік 2001 Генерал Иванов




Поделиться с друзьями:


Дата добавления: 2014-12-27; Просмотров: 431; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.052 сек.