Директиви препроцесора в Visual C # (Sharp)

Раніше в цій главі розглядалося використання символу # і умовних Оператив для включення або виключення коду з компіляції На технічному жаргоні це називається попередньою обробкою (Preprocessing) коду, а оператори Нива директивами препроцесора У табл 61 наведений список директив прроцессора

Таблиця 61Директиви препроцесора

Директива

Опис

#define

Застосовується для визначення ідентифікаторів компіляції, таких як ідентифікаторINTEGRATE_TESTS, Використаний в прикладі цієї Гли Визначення виконується на початку файлу вихідного коду, щоб активувати умовні оператори препроцесора, використовувані у всьому файлі вихідного коду Область видимості директиви # def ine обмежитися одним файлом вихідного коду

#undef

Застосовується для скасування ухвали ідентифікатора Директива

# Undef застосовується при необхідності змінити глобальну установку Припустимо, що ідентифікатор встановлений глобально, але для виразно файлу вихідного коду необхідно поведінку, начебто б даний ідентифікатор ні встановлено У такому випадку застосовується директив # undef Іншим способом отримати таку поведінку можна за допомогою символу перед ідентифікатором

Таблиця 61(Закінчення)

Директива

Опис

# If і # єп-dif

Використовуються для умовного включення або виключення фрагмента иодную коду Умовні директиви застосовуються для визначення різних конфігурацій вихідного коду, наприклад, визначення отладочной або промислового складання

#elif

Дана директива дозволяє визначити кілька умов для включені або виключення коду з компіляції Директива # elif застосовується для визначення кількох різних конфігурацій вихідного коду, нрімер, для отладочной, промислової і підвищеної проізводітельнті зборок

#else

Визначає блоку коду, який включається, якщо оператори # if НЕ аівіруются

# Region і

#endregion

Дані директиви не мають ніякого відношення до компіляції початково коду Вони застосовуються Visual Studio для створення областей початково коду, які можна згортати подібно згортання дерева каталогів Таким чином, можна тимчасово приховати блок коду Постійного прокручування довгих файлів вихідного коду не дає нічого в термінах продуктивності Звернувши код, ми можемо зменшити обм прокрутки або зовсім усунути її, а згорнутий код можна развеуть в будь-який час

У наступному фрагменті коду демонструється використання директив препрессора:

#define ACTIVATE_1

#undef ACTIVATE_2

namespace TestDefine { class Example {

#if ACTIVATE_1

int _dataMember

#elif  N0_ACTIVATE_10 int _dataMember3

#else

int _defaultValue

#endif

}

}

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

ПРИМІТКА

Visual С # Express не дозволяє вибрати отладочную або кінцеву версію разрабиваемог про коду Дл я цієї можливості необхідна повна версія Visual Studio

Декоративні символи можна порівняти з інформаційними дорожніми знаками При виконанні в отладочном режимі ці знаки надають обширну іормацію, типу: Зараз викликається такий-то метод в такому-то файлі вихідного коду або Оба-на, цей код властивості у вихідному файлі не працює належним обром. У кінцевій версії декоративні символи надають лише коротку інформацію, типу До міста X залишилосяукілометрів . Хоча ця інформація і краще ніж нічого, тим не менш, вона дуже обмежена, наприклад, вона нічого не говорить нам про проміжні населених пунктах

У прикладах цієї глави область видимості блоків get і set властивостей завжди була однаковою Але це не є обовязковим, і ці блоки можуть мати різну оасть видимості Різна область видимості встановлюється з метою дозволити реалізацію логіки, коли класам в ланцюжку спадкування дозволяється прісваать властивості значення, а класам поза цього ланцюжка дозволяється тільки читання властивості Ось приклад установки блоку set властивості як protected, а блоку get – як public:

class PropertyScopeExample { int _value

public int Value { protected set {

_value = value

}

get {

return _value

}

}

}

Ключове слово abstract

У прикладах цієї глави ключове слово abstract використовувалося для оголошення класу, до якого можна звертатися, але з якого не можна створювати екземпляри Крім цього призначення, за допомогою ключового слова abstract можна визначати методи з відкладеним реалізацією Метою такого оголошення є дозволити розробнику визначити свій намір у базовому класі, а реалізувати в проіодном класі У реалізації класів HotelCurrencyTrader І ActiveCurrencyTrader були визначені два методи: ConvertTo О І ConvertFrom *) Розробник міг би

вирішити, що ці класи містять загальні методи, які можна було б попрілості в базовому класі CurrencyTrader Це непогана ідея Повернемося до класу CurrencyTrader і додамо в нього ці два методи як абстрактні (Виділено жіим шрифтом):

public abstract class CurrencyTrader { private double _exchangeRate

protected double ExchangeRate { get {

return _exchangeRate

}

set {

_exchangeRate = value

}

}

protected double ConvertValue(double input) { return _exchangeRate * input

}

protected double ConvertValuelnverse(double input) { return input / _exchangeRate

}

public abstract double ConvertTo(double value) public abstract double ConvertFrom(double value)

}

Клас, в якому оголошується абстрактний метод з відкладеним реалізацією, також необхідно оголосити абстрактним

Будь клас, який успадковують від CurrencyTrader, повинен реалізувати методи ConvertToо І ConvertFrom () У разі класів HotelCurrencyTrader І Ac-tiveCurrencyTrader це не є проблемою, тому що в них ці методи вже реаловани Але їх необхідно злегка змінити, як показано тут:

public override double ConvertTo(double value) {

//  ..

}

public override double ConvertFrom(double value) {

II..

}

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

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

до реалізації класу ActiveCurrencyTrader, в якому абстрактні методи не Реіз Щоб використовувати цей клас і метод ConvertToO, можна написати такий код:

ActiveCurrencyTrader els = new ActiveCurrencyTrader() double converted = elsConvertTo(1000)

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

public double ConvertToTextField(ActiveCurrencyTrader els) { return  elsConvertTo(intParse(textlText))

}

Але реалізація методу ConvertToTextField () містить серйозну помилку – у ньому передбачається, що перетворення завжди буде виконуватися за допомогою класу ActiveCurenceTrader Якби ми захотіли використовувати клас HotelcurrencyTrader, то нам довелося б реалізувати інший метод, з парамеом типу HotelcurrencyTrader

Дана ситуація є класичним прикладом проблеми поліморфізму, для вирішення якої і застосовуються абстрактні методи Подивіться на модіфіцованний метод ConvertToTextField ():

public double ConvertToTextField(CurrencyTrader els) { return  elsConvertTo(intParse(textlText))

}

У даній реалізації методу ConvertToTextField () використовується базовий клас CurrencyTrader, а Т К метод и ConvertToO І ConvertFrom () оголошені, ТО ДО НИХ можна звертатися

Яким чином викликається метод ConvertToTextField () і створюється екземпляр клас а HotelcurrencyTrader АБО клас а ActiveCurrencyTrader, У ЦІЙ глав е раматріваться не буде, т к поліморфізм обговорюється в наступному розділі Коли будете читати цю главу, в якій розглядаються такі поняття, як компонеи і інтерфейси, то просто майте на увазі, що застосуванням ключового слова abstract досягається те ж саме, що і з допомогою цих концепцій

У цьому розділі ми розглянули деякі основньге поняття обєктно-орієнтованого програмування З цього матеріалу рекомендується запамятати такі кльові аспекти

• Код складається з структурної функціональності (або функціональності базово класу) та архітектурної функціональності, повязаної з певною облтью діяльності

• Функціональність базового класу спрямована на вирішення певної прлеми Проблема може бути вирішена і загальним способом, але це рішення буде застосовано тільки до даної проблеми Функціональність базового класу Труета від розробника специфічних знань в даній області Це можна раматрівать як реалізацію калькулятора, при якій головним завданням разротчіка є забезпечення правильності обчислень

• Архітектурна робоча функціональність є функціональністю більш високого рівня, для реалізації якої потрібно загальне знання області деельності Ідея полягає в тому, щоб з допомогою базових класів вирішити прлему з певної галузі діяльності Це можна розглядати як використання калькулятора, де вашим головним завданням є отримати рультати обчислень

П Властивості необхідно використовувати, не надаючи до їх членам даних загально доступу

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

• Загалом, класи не повинні представляти доступ до свого стану Щоб не представляти стан, потрібно створювати методи, які реалізують загальне призначення класу

D Спадкування є фундаментальною частиною С #, і необхідно знати, як користуватися нею Одним із способів реалізації спадкування є ісполованіе ключового слова abstract

П Підміна (overriding) означає, що ми залишаємо інтерфейс без змін, але модифікуємо поведінку

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

П Оператори умовної компіляції застосовуються для включення або виключення конкретних блоків коду в певні версії програми

Про Часткові класи застосовуються для відокремлення функціональності, що має спеціальне призначення У прикладі даної глави часткові класи іспользалісь для додавання тестового коду без порушення заборони на надання стану

Джерело: Гросс К С # 2008: Пер з англ – СПб: БХВ-Петербург, 2009 – 576 е: ил – (Самовчитель)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*