Треки
/
C#
C#
/
Салабус
/
Приведення типів
Пр

Приведення типів у C#

4 вправи

Про концепцію Приведення типів

Приведення типів і перетворення типів - це різні способи змінити вираз з одного типу даних на інший.

У документації C# перетворення типів класифікують як використання оператора as або оператора is. Приведення типів визначають як використання оператора приведення.

У C# дуже часто, поза межами числових значень і ієрархій класів, нам доведеться виконувати перетворення, викликаючи якийсь член цільового типу, наприклад Int32.Parse(), який перетворює рядок тексту (англ. string) на ціле число, або викликаючи член вихідного типу, наприклад object.ToString(). Про це варто памʼятати розробникам JavaScript та інших динамічних мов.

Зауважимо, що доступні оператори неявного та явного приведення operators (про них ідеться в operator-overloading), які дають змогу додати досить довільне приведення до власних типів.

Приведення примітивних типів - неявне

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

Неявне приведення не позначається якимось спеціальним синтаксисом. Наприклад:

int myInt = 1729;
long myLong = myInt;

Немає неявного перетворення числового виразу (або рядка тексту) на bool. Бібліотека базових класів (BCL) надає Convert.ToBoolean() для цієї мети.

Вираз типу char можна неявно привести до int. Приведення в протилежному напрямку має бути явним. Не всі значення int є припустимими символами UTF-16.

Приведення примітивних типів - явне

Якщо числові типи не можна неявно привести, зазвичай можна використати оператор явного приведення.

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

Вираз типу int можна явно привести до char. Це може призвести до недійсного char.

Приведення примітивних типів - приклади

int largeInt = Int32.MaxValue;
int largeNegInt = Int32.MinValue;
ushort shortUnsignedInt = ushort.MaxValue;
float largeFloat = float.MaxValue;
float smallFloat = 17.29f;

// implicit cast
int from_ushort = shortUnsignedInt;          // 65535
float from_int = largeInt;                   // -21474836E+09
int from_char = 'a';                         // 96

// explicit cast
uint from_largeInt = (uint)largeInt;         // 2147483647
uint from_neg = (uint) largeNegInt;          // 2147483648 or OverflowException is thrown (if checked)
int from_smallFloat = (int) smallFloat;      // 17
int from_largeFloat = (int) largeFloat;      // -2147483648 or OverflowException is thrown (if checked)
char from_intc = (char) 32;                  // ' '
char from_invalid_int = (char) 0xdcbf;       // invalid char - no exception thrown

// no cast available
int fromString = Int32.Parse("42");          // 42
string toString = largeInt.ToString();       // "2147483647"
int fromString_bad = Int32.Parse("forty two");     // FormatException is thrown

Додатково про ключове слово checked можна прочитати в цій статті.

Перетворення типів для типів в ієрархії

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

IList<int> ll = new List<int>();

Оператор приведення можна використати, щоб перетворити базовий клас на похідний.

IList<int> ll = new List<int>();
List<int> l = (List<int>)ll;

Якщо приведення не вдається, бо тип виразу, який приводиться, не повʼязаний з типом, до якого його приводять, викидається виняток InvalidCastException.

Звичніший підхід до таких перетворень типів - використати ключове слово is:

interface IFoo { int Bar(); }
class Foo : IFoo { public int Bar() { return 42; }}
Object r = new Random();
IFoo ifoo = new Foo();
Object o = new Foo();

int result = 1729;

if (ifoo is Foo foo)
{
    result = foo.Bar();
}
// result == 42

result = 1729;
if (o is Foo foo2)
{
    result = foo2.Bar();
}
// result == 42

result = 1729;
if (r is Foo foo3)
{
    result = foo3.Bar();
}
// result == 1729

Ключове слово as виконує подібну функцію до is, наприклад: var foo = ifoo as Foo;. У цьому прикладі foo буде null, якщо ifoo не має типу Foo; інакше ifoo буде присвоєно йому.

Власний оператор приведення

Типи можуть визначати власні явні та неявні оператори приведення.

Приклади явних і неявних приведень у BCL - це перетворення зі структури BigInteger на інші числові типи та навпаки.

Використання typeof

Якщо потрібно визначити точний тип обʼєкта, то is може бути трохи занадто поблажливим, адже він перетворює обʼєкт на клас або будь-який з його базових класів. У цьому випадку допоможуть typeof і Object.GetType().

object o = new List<int>();

o is ICollection<int> // true
o.GetType() == typeof(ICollection<int>) // false
o is List<int> // true
o.GetType() == typeof(List<int>) // true
Редагувати через GitHub Посилання відкривається в новому вікні або вкладці

Вивчити концепцію Приведення типів

Практика заблокована

Розблокуйте ще 3 вправи, щоб практикувати концепцію Приведення типів