Скачиваний:
29
Добавлен:
26.03.2016
Размер:
429.43 Кб
Скачать

Оператори as і is

Через те що object є загальним базовим типом, будь-яке посилання на клас можна перетворити в посилання на object, а посилання на object можна спробувати перетворити в посилання на будь-який клас. Слово «спробувати» сказано не випадково, тому що явне перетворення (з нащадка в батька) проходить не завжди, бо нащадок - це розширення батька. Приведення "вниз" завжди виконується явно. Існують спеціальні оператори, які визначають сумісність типів. Це оператори з ключовими словами as та is. Вони працюють на сумісність не тільки таких складних типів, як класи, але і для базових типів, таких як, наприклад, int. Як працює оператор is, видно з прикладу, приведеного в лістингу 8.15.

Лістинг 8.15

using System;

namespace app33_as_and_is

{

public class test

{

static void Main()

{

String derived_obj = "Dummy"; // Похідний об'єкт класу String (із статичних

// класів екземпляри не створюються)

Object base_objl = new Object (); // Базовий об'єкт

Object base_obj2 = derived_obj; // Явне перетворення: запам'ятовування

// посилання в базовому об'єкті

Console.WriteLine ("base_obj2 {0} String", base_obj2 is String ? "є" : "не є");

Console.WriteLine ("base_objl {0} String", base_objl is String ? "є" : "не є");

Console.WriteLine ("derived_obj {0} Object", derived_obj is Object ? "є" : "не є");

int j = 123;

object b = j;

object obj = new Object () ;

Console.WriteLine ("b {0} int", b is int ? "є" : "не є");

Console.WriteLine ("obj {0} int", obj is int ? "є" : "не є");

Console.WriteLine("b {0} System.ValueType", b is ValueType ? "є" : "не є");

float f=12.3f;

Console.WriteLine ("f {0} int", f is int ? "є" : "не є");

Console.Read();

}

}

}

Результат роботи програми представлений на рис. 8.12.

Рис. 8.12. Перевірка роботи оператора is

У програмі створюється екземпляр класу String. Це системний статичний клас. З таких класів екземпляри не створюються, тому змінній цього типу derived_Obj здійснюється присвоєння значення безпосередньо. Вважатимемо, що це - похідний клас, бо всі класи, в тому числі і String, походять від загального батька - класу Object. Його і почнемо вважати батьком. Його екземпляри - base_Obj1 і base_Obj2. В останньому запам'ятовується посилання на похідний клас derived_Obj. А далі йдуть перевірки за допомогою оператора is на сумісність типів. Перевірка здійснюється всередині оператора Console.WriteLine(), у якому як вираз, що виводиться на екран, служить вираз вигляду base_Obj2 is String ? "є" : "не є". Такий оператора ми ще не зустрічали. Його позначення – знак питання (?). Він називається тернарним (з трьох частин) умовним оператором на відміну від бінарного (з двох частин) умовного оператора if...else. Загальна форма такого оператора:

Вираз1 ? Вираз2 : Вираз3;

Тут Вираз1 повинен відноситися до типу bool (тут і задається умова), а Вираз2 і Вираз3 - до одного і того ж типу. Зверніть увагу на застосування двокрапки і її місцеположення в операторі ?. Результат визначається таким чином. Спочатку обчислюється Вираз1. Якщо воно істинне (True), то обчислюється Вираз2, і отриманий результат - результат всього оператора. Якщо ж Вираз1 виявляється помилковим (значення - False), то обчислюється Вираз3, і його значення стає загальним результатом.

У нас в програмі записано

base_Obj2 is String ? "є" : "не є"

Тобто Вираз1 - це base_Obj2 is String (перевірка: чи є base_Obj2 типом String). Цей вираз можна було б в програмі записати у вигляді

bool b1= base_Obj2 is String;

Тоді вираз

base_Obj2 is String ? "є" : "не є"

був би таким:

b1 ? "є" : "не є"

У результаті оператор

Console.WriteLine("base_Obj2 {0} String", b1 ? "є" : "не є");

працює так: виводиться base_Obj2 (те, що не відноситься до формату, виводиться один до одного), потім обробляється формат, тобто вибирається для виведення із списку аргументів перший (він у нас єдиний). Це якраз тернарний умовний оператор-вираз. Він обчислюється і виводиться. Після цього за форматом {0} знову йдуть не форматні символи (String). Вони виводяться на екран без зміни.

Приклад роботи з оператором is показаний в програмі, приведеній у лістингу 8.16. Результат її роботи представлений на рис. 8.13.

Лістинг 8.16

using System;

namespace App33_as_and_is2

{

public class BaseType { }

public class DerivedType : BaseType { }

public class Program

{

static void Main()

{

Console.WriteLine("Перевірка оператора as");

DerivedType derived_Obj = new DerivedType(); // об'єкт похідного класу

BaseType base_Objl = new BaseType(); // Об'єкт базового класу

BaseType base_Obj2 = derived_Obj; // Неявне перетворення в базовий клас

// Перевірка, чи є базовий тип після перетворення в нього похідного

// похідним типом. Якщо ні, то результатом as буде посилання null

DerivedType derived_Obj2 = base_Obj2 as DerivedType;

if (derived_Obj2 != null)

{

Console.WriteLine("Похідний тип " + "перетворився в базовий вдало");

}

else

{

Console.WriteLine("Перетворення похідного " + "типу в базовий не вдале");

}

// Перевірка: чи є базовий тип похідним

derived_Obj2 = base_Objl as DerivedType;

if (derived_Obj2 != null)

{

Console.WriteLine("Базовий тип перетворився " + "в похідний вдало");

}

else

{

Console.WriteLine("Перетворення базового типу " + "у похідний не вдале");

}

// Перевірка: чи є похідний тип базовим

BaseType base_Obj3 = derived_Obj as BaseType;

if (base_Obj3 != null)

{

Console.WriteLine("Похідний тип сумісний " + "з базовим");

}

else

{

Console.WriteLine("Похідний тип не сумісний " + "з базовим");

}

Console.Read();

}

}

}

Оператор as на відміну від is при несумісності типів видає значення null.

Рис. 8.13. Перевірка роботи оператора as