- умовний вираз У C #, як і в C ++, дозволені умовні вирази. Звичайно, без них можна обійтися, замінивши...
- Операція ?? - нова операція C # 2.0
- Лямбда-оператор - нова операція в C # 3.0
умовний вираз
У C #, як і в C ++, дозволені умовні вирази. Звичайно, без них можна обійтися, замінивши їх умовним оператором. Ось простий приклад їх використання, що пояснює синтаксис їх записи:
// Умовний вираз int a = 7, b = 9, max; max = (a> b)? a: b;
Умовний вираз починається з умови, укладеного в круглі дужки, після якого слід знак питання і пара виразів, розділених двокрапкою ":". Умова задається виразом типу bool. Якщо воно істинне, то з пари виразів вибирається перше, в іншому випадку результатом є значення другого виразу. В даному прикладі змінна max отримає значення 9.
Зауважте, умовний вираз є прикладом тернарного вираження - вираження з трьома операндами. І тут, як і в разі умовних логічних операцій, не потрібно, щоб всі операнди були визначені. Якщо булевский операнд визначено і має значення true, то обчислюється другий операнд, а третій операнд не вирахував і може бути в цей момент не визначений.
операція присвоювання
Нам залишилося розглянути останню за пріоритетом, але не за важливістю операцію присвоювання. Синтаксично присвоювання в мові C # є окремим випадком виразу і може зустрічатися скрізь, де дозволено поява виразів. Вираз присвоювання є виразом з побічним ефектом. Воно не тільки повертає значення деякого типу як результат, але і змінює значення однієї або декількох змінних в якості побічного ефекту. У реальних програмах присвоювання найчастіше зустрічається не як вираз, а як оператор присвоювання. Перетворити вираз присвоювання в оператор присвоювання простіше простого. Потрібно вираз закінчити символом крапка з комою і використовувати його там, де дозволяється використовувати оператори.
Почнемо з формального визначення синтаксису вираження привласнення:
<Змінна> <знак присвоювання> <вираз>
Знаків присвоювання багато, вони перераховані в таблиці 3.1 . Найчастіше використовується знак рівності, але іноді йому можуть передувати і інші знаки операцій. З чим пов'язана наявність багатьох знаків у однієї операції? Мови C # це дісталося в спадок від мови С ++, де автори мови були великими любителями стислості запису на шкоду її ясності. Тому в мові допустимі такі вирази, як x ++, x + = y, мало зрозумілі пересічному математику. Друге з цих виразів є виразом присвоювання і задовольняє вище наведеним синтаксису зі знаком присвоювання + =. Його можна розглядати як короткий запис вираження . Аналогічний сенс мають і інші знаки присвоювання - (* =, / = і інші).
У правій частині синтаксичної формули, яка визначає вираз присвоювання, варто вираз, яке може бути в свою чергу виразом присвоювання. Звідси випливає допустимість множинного присвоювання. Синтаксично цілком коректний такий приклад:
/// <summary> /// Множина присвоювання /// </ summary> static void AssignTest () {double x = 1, y = 2, z = 3, w = 9, u = 7, v = 5; if ((x + = y - = z + = w * = (u + v) / (u - v)) <0) Console.WriteLine ( "x = {0}, y = {1}, z = { 2}, "+" w = {3}, u = {{4}, v = {5} ", x, y, z, w, u, v); }
В операторі if записано вираз, що задає множину присвоювання. Яка семантика, як обчислюються вирази присвоювання?
Операція присвоювання є правобічної операцією, і особливістю обчислення виразу присвоювання є те, що воно обчислюється справа наліво. У нашому прикладі спочатку буде обчислено саме праве вираз (u + v) / (u - v), значення якого буде дорівнює 6. Рухаючись ліворуч по ходу привласнення, значення виразу буде змінюватися. Останнім буде обчислено вираз, яке отримає змінна x. Значення цього виразу одно -54, саме воно є остаточним значенням вираження множини присвоювання і братиме участь в порівнянні з нулем. Умова в операторі if отримає значення true, і метод WriteLine виведе на консоль значення змінних, отриманих ними як побічний результат обчислення виразу присвоювання. Ці значення відповідно рівні: -54, -55, 57, 54, 7, 5. Зауважте, дужки, що оточують вираз присвоювання, необхідні, інакше операція порівняння виконувалася б раніше, ніж присвоювання, що призводило б до помилки.
Для пояснення деталей семантики виразів присвоювання використана досить екзотична конструкція в операторі if. У реальних програмах такі конструкції застосовувати не слід. Вони "від лукавого". Простота записи і понимаемость - одні з головних критеріїв при створенні промислового коду. При вивченні можливостей мови допустимо розгляд екзотичних випадків.
Операція ?? - нова операція C # 2.0
Ця операція вже розглядалася в попередній лекції, коли мова йшла про типах, що допускають значення null. Нагадаю, все посилальні типи спочатку допускають null в якості можливого значення. Таке значення посилальної змінної задає невизначену посилання, посилання на неіснуючий об'єкт. Значні типи значення null не містять, але можна визначити розширений значимий тип, що включає значення null. Синтаксично, якщо T - ім'я значимого типу, то T? - це ім'я розширеного типу. Операція? ? визначена над операндами, що допускають значення null. Її головне завдання - привласнити змінній значення, відмінне від null, тому іноді її називають операцією склеювання, оскільки вона дозволяє "приклеїти" до null значення. Розглянемо її визначення:
Якщо операнд A відмінний від null, то він і повертається в якості результату операції. Якщо ж він має значення null, то результатом є операнд B. Цю операцію особливо зручно використовувати при приведенні типу T? до типу T. Розглянемо простий приклад:
int? x = null; ... int y = x ?? 0;
Зауважте, якщо між двома привласнення змінним x не набула значення, відмінне від null, то змінна y в результаті отримає значення 0.
У відсутності такої операції нам довелося б писати для обчислення у таку еквівалентну конструкцію:
int y = (x! = null)? (Int) x: 0
Лямбда-оператор - нова операція в C # 3.0
У третій версії мови з'явилася нова операція, яка називається лямбда-оператором, і, відповідно, новий тип виразів, які називаються лямбда-виразами. Ця операція має той же пріоритет, що і операція присвоювання, і, так само як і остання, є правобічної операцією. Синтаксис лямбда-виразів наступний:
<(Список вхідних аргументів)> => <вираз>
Змістовно вираз в правій частині задає опис функції, аргументи якої задаються списком лівій частині. Такий опис являє собою опис анонімної функції - функції без імені - і може бути використано, наприклад, при завданні примірника делегата. Найчастіше функція залежить від одного аргументу, і тоді в лівій частині можна вказувати тільки ім'я цього аргументу, опускаючи дужки.
Детально цей механізм буде розглянуто в окремій лекції нашого курсу, а поки наведемо перший простий приклад використання цієї операції. Розглянемо наступну задачу. Нехай дано масив чисел X і задана функція F (x). Потрібно знайти мінімальне значення цієї функції, коли аргументи задаються елементами масиву X. Звичайно ж, можна створити метод, який реалізує обчислення функції F (x), але можна скористатися анонімною функцією, заданою лямбда-виразом, що демонструє наступний приклад:
/// <summary> /// Лямбда-оператор і лямбда-вираз /// </ summary> static void Lambda () {Random rnd = new Random (); const int size = 5; int [] numbers = new int [size]; int a = rnd.Next (-10, 10), b = rnd.Next (-10, 10), c = rnd.Next (-10, 10); Console.WriteLine ( "a = {0}, b = {1}, c = {2}", a, b, c); for (int i = 0; i <size; i ++) {numbers [i] = rnd.Next (10); Console.Write ( "X [{0}] = {1},", i, numbers [i]); } Int minValue = numbers.Min (x => a * x * x + b * x + c); Console.WriteLine ( "Min (a * x ^ 2 + b * x + c) = {0}", minValue); }
Велика частина в цьому прикладі пов'язана з моделюванням масиву чисел і коефіцієнтів функції. Знаходження мінімуму функції задається одним рядком:
int minValue = numbers.Min (x => a * x * x + b * x + c);
Тут функція Min послідовно перебирає елементи масиву, формуючи аргумент x функції, а лямбда-вираз перетворює його в значення функції від цього аргументу. В результаті повертається мінімальне значення функції. Результати роботи методу Lambda можна бачити на Мал. 3.5 .
На цьому закінчимо розгляд операцій мови C #, але продовжимо розмову про деякі питання, пов'язані з обчисленням виразів.
Операція ?З чим пов'язана наявність багатьох знаків у однієї операції?
Яка семантика, як обчислюються вирази присвоювання?
Операція ?
Синтаксично, якщо T - ім'я значимого типу, то T?
Операція?
Цю операцію особливо зручно використовувати при приведенні типу T?
Int y = x ?