Узагальнення. NET

У чолі 9 ми розглянули використання списків, делегатів і лямбда-виразів Там же був показаний приклад узагальнень NET при використанні списків для управління колекцією обєктів У цьому розділі ми розглянемо узагальнення NET більш докладно, включаючи використання їх у контексті чорного ящика (тобто коли код нічого не знає про специфіку типів параметрів узагальнень NET) Крім цього, буде представлена ​​більш детально реалізація лямбда-виразів Для демонсаціі цих концепцій ми розширимо приклад електронної таблиці, використані вчолі 9Мета – придбання хорошого досвіду у застосуванні узагальнень і лямбда-виразів NET, які ви, швидше за все, будете використовувати у своєму робочому коді Це дозволить знизити можливість виникнення неприємних сюрізов при розробці проектів

В принципі, у використанні узагальнень NET немає нагальної необхідності, і тому можна припустити, що цю главу можна було б і пропустити Але це буде помилкове припущення З такою ж легкістю можна було б сказати, що немає нагальної необхідності у використанні властивостей або будь-яких інших структур С #, що розширюють можливості програмування Використання таких конструкцій, як властивості С # та узагальнення NET, надає нам можливості елегантного і виразного програмування Щоб краще зрозуміти, що я паюсь сказати, погляньте на наступну фразу:

Качки ходять плоскі лапи крякають голосно

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

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

Додавання узагальнень NET в С # роблять його подібним наступного речення:

Качки ходять смішно, тому, що у них плоскі лапи, а коли вони крякають, то дуже голосно

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

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

Прикладом, що ілюструє, як використання узагальнень NET робить код як більш ясним, так і більш коротким, ніж код, який не використовує узагальнень NET, може служити така структура, як контейнер Контейнер – Це тип, використовуючи для управління іншими типами Списки і колекції є прикладами контейнера Для простоти, розглянемо контейнер, що містить лише один ЕЛЕНТ Далі наводиться коротка версія, використовує тип object:

public class Container { object _managed

public Container(object toManage) {

_managed = toManage

}

public object Managed { get {

return _managed

}

}

}

У даному коді клас container має конструктор з параметром і одним свойс, Managed, яке посилається на змінну managed Метою даного класу є привласнити в конструкторі значення обєкту, до якого можна звертатись за допомогою властивості Клас Container не знає, ні що робить змінна

_managed, ні які її можливості Але йому це і не потрібно знати, т к клас

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

Клас container можна використовувати таким чином:

Container container = new Container(new MyType())

(containerManaged as MyType)Method))

При створенні екземпляра класу Container члену даних managed присвоюється екземпляр типу мутуре Тип мутуре використовується в демонстраційних цілях і має один метод – Method () Щоб отримати і використовувати керований тип, що виконують-

няется звернення до властивості Managed Але тоді метод Method про не можна викликати безпосередньо, т к властивість Managed має тип object тому необхідно виконати приведення типу властивості до типу МуТуре, щоб зробити виклик методу Method () легітимним

Результатом приведення типу за допомогою оператора as буде дійсний еемпляр типу мутуре або значення null, що викличе виключення звернення до невому обєкту Тому для безпечного використання властивості Managed потрібен наступний код:

Container container = new Container (new МуТуре ())

if (containerManaged is МуТуре) {

(ContainerManaged as МуТуре) Method ()

}

Доданий код виділений жирним шрифтом Це оператор if для перевірки, явлтся чи тип, до якого звертається контейнер, типом мутуре Незважаючи на цю перевірку, в коді відсутні вказівки, що необхідно робити у випадку отріцельного результату цієї перевірки, тобто коли властивість Managed не відноситься до ту мутуре Необхідність виконання перевірки на звернення контейнера до Прилиньте типу, а також в альтернативному плані дій у разі негативного результату перевірки означає додавання досить великого обсягу дополнельного коду до первісного коду Початковий код можна порівняти з першою фразою про качок – швидше за все, ми уловимо загальний зміст сказаного, але навряд чи будемо впевнені в сенсі почутого на всі 100%

Тепер подивимося на код, який реалізує контейнер за допомогою узагальнень NET:

public class GenericsContainer&ltManagedType&gt { ManagedType _managed

public GenericsContainer(ManagedType toManage) {

_managed = toManage

}

public ManagedType Managed { get {

return „managed

}

}

}

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

Параметри узагальнень NET асоціюються з типами, такими як класи і інтеейси, або ж з методами У разі класу Genericscontainer параметр узагальнюючи ManagedType є типом

ПРИМІТКА

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

У контейнері GenericsContainer обєкт ManagedType використовується як ідеіфікатора замість ідентифікатора object в типі container Дане використання є практичним правилом Завжди, коли обєкт використовується загальним чином для визначення типу, швидше за все, можна застосувати узагальнення NET

У наступному коді демонструється використання GenericsContainer З MyType

GenericsContainer&ltMyType&gt container =

new GenericsContainer <МуТуре> (new MyType ()) containerManagedMethod ()

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

Середа виконання NET згенерує тип, чиє призначення схоже на призначення, виражене в наступному коді:

public class GenericsContainerMyType { MyType _managed

public GenericsContainer(MyType toManage) {

„managed = toManage

}

public MyType Managed { get {

return _managed

}

}

}

Компілятор C # компілює загальний тип NET у вигляді неповного типу При конкрізаціі неповного типу NET створює повністю новий тип, не вимагаючи для цього

ніяких спеціальних дій з боку розробника Це означає, що якщо GenericsContainer використовується з 15 різними типами, то при виконанні пррамми NET згенерує 15 різних його визначень

Абстракції і узагальнення NET

Використовуючи узагальнення NET, можна забезпечити вираження своїх ідей в коді долим чином, але ціною за це буде ускладнення коду Це буде подібно докладного пропозицією про качок Щоб створити цю пропозицію, нам довелося вивчити і вжити додаткові граматичні правила Використання узагальнень

. NET вимагає розширених знань про структури програмування, зокрема зній, як створювати абстракції

Узагальнення NET є абстракціями Точно так само, як інтерфейси є абстракціями класів, узагальнення NET є абстракціями над інтерфейсами Інтерфейси визначають наміри, а узагальнення NET – Абстрактні реалізації намірів

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

Джерело: Гросс К С # 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>

*

*