Процедури і функції

Процедури і функції C# практично повністю відповідають їх визначенням в мові C++. Фактично, в мові З відсутнє визначення процедури, прийняте в інших мовах програмування. Якщо визначити функцію, яка не повертає ніякого результату (тип void) в зухвалу програму, ми отримаємо аналог процедури в інших мовах програмування. Основна відмінність процедури від функції полягає в тому, що функція повинна завжди повертати деякий результат, і, крім того, повинна бути викликана у виразі. Процедура ж не повертає ніякого результату, її виклик здійснюється за допомогою оператора мови; крім того, вона має вхідні і вихідні аргументи, причому вихідних аргументів може бути досить багато. Таким чином, створювати функцію доцільно тільки у тому випадку, коли необхідно провести які-небудь обчислення, в результаті яких повинен бути отриманий результат у вигляді одного значення. Процедуру - відповідно у разі, коли може бути отриманий результат, що є набором яких-небудь значень.

Проте існує ряд нововведень, які стосуються функцій, що з'явилися в C#. Найбільш важливою особливістю використання функцій і процедур в C# є те, що, оскільки C# є повністю об'єктно-орієнтованою мовою програмування, функції не можуть існувати у відриві від класів. Тому функцію бібліотек процедур і функцій в C# виконують бібліотеки класів.

Оскільки відмінності між процедурами і функціями достатньо умовні, а існувати вони можуть тільки усередині класів, надалі як синонім процедур і функцій використовуватимемо термін "метод".

Синтаксис опису методів достатньо простий:

[атрибути][модифікатори]{void | тип результату функції}ім'я методу ([список формальних аргументів])

Ім'я методу і список формальних аргументів представляють сигнатуру методу. Квадратні дужки, як це прийнято, показують, що їх вміст може бути опущене при описі методу.

Атрибути і модифікатори є дуже важливій складовій опису будь-якого методу, проте вони будуть розглянуті при описі класів, оскільки мають до цього найбезпосередніше відношення. Поки ж можна вважати, що під модифікаторами маються на увазі модифікатори доступу, з яких ми розглядатимемо поки тільки два: private і public. Private означає, що даний метод є закритим, відповідно доступ до нього можуть отримати тільки методи того класу, в якому він оголошений. Public - навпаки, означає, що доступ до даного методу є відкритим і загальнодоступним з будь-якої точки застосування.

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

Простими прикладами опису функцій є наступні:

private void A(){ public int B(){ public long Stepen(int а, int b) { long r; r = (long)Math.Pow(а, b); return (r); }

Тут метод A є закритою процедурою, методи B і Stepen - відкритими функціями. У методів A і B не визначені формальні параметри, тоді як у методу Stepen два формальні параметри: а і b.

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

[ref|out|params] тип_аргумента имя_аргумента

При цьому обов'язковою є вказівка типу аргументу, який може бути скалярним, масивом, класом, структурою, - будь-яким типом, допустимим в C#.

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

Всі аргументи методів можна розділити на три групи: вхідні, вихідні, що оновлюються.

Вхідні необхідні для передачі інформації методу, їх значення в тілі методу доступні тільки для читання. Вихідними є результати методу, вони отримують значення в ході роботи методу. Оновлювані здатні виконувати обидві функції. Вихідні аргументи повинні бути помічені ключовим словом out, при цьому в тілі методу повинен бути обов'язково присутнім оператор привласнення значення цьому аргументу; оновлювані аргументи позначаються за допомогою ключового слова ref.

Як приклад злегка модернізуємо описаний раніше метод Stepen:

public void Stepen(out long r,int а, int b){ r = (long)Math.Pow(а, b);}

Як видно з прикладу, функція Stepen була фактично перетворена в процедуру (тип повертаного функцією значення був змінений на void). Також був доданий формальний аргумент r, використовуваний як вихідного. У тілі методу цьому аргументу привласнюється значення, яке згодом може бути використане в зухвалій програмі.

Виклик цього методу може бути здійснений таким чином:

long s;Stepen(out s, 2, 6);Response.Write(s.ToString());

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

Розглянемо приклад передачі довільної кількості значень початкових даних в метод для їх обробки. Як вже згадувалося вищим, для цього необхідно використовувати ключове слово params. Створимо приклад, в якому в метод Stepen може передаватися довільна кількість чисел для знаходження суми їх квадратів. Оголошення методу в цьому випадку виглядає таким чином:

public void Stepen(out long r, int а, params int[] b){ r = 0; foreach (int i in b) r += (long)Math.Pow(i, а);}

Виклик методу може бути здійснений так:

int[] digits ={1,8,4};Stepen(out s, 2, digits);Response.Write(s.ToString());

Видно, що для виклику методу необхідно сформувати масив цілих чисел, який потім слід передати як третього аргументу в метод. Результат обчислення суми накопичується в змінній r, а потім передається в змінну s зухвалої програми.

Результат роботи програми показаний на рис. 3.8.

Мал. 3.8. Результат виконання методу Stepen для розрахунку значення суми квадратів чисел

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

Розглянемо приклад створення процедури, що дозволяє отримувати масив чисел, підносити кожне з них до певного ступеня, передавати результат розрахунку в зухвалу програму і виводити результат на екран.

Процедура в цьому випадку виглядатиме таким чином:

public void Stepen(out long[] r,int а, params int[] b){ r=new long[0]; Array.Resize(ref r,b.Length); int j=0; foreach (int i in b) r[j++]= (long)Math.Pow(i, а);}

Тут необхідно відзначити наступні важливі особливості. По-перше, як параметр, що повертає значення в зухвалу програму, використаний масив чисел типу long. По-друге, перш ніж стане можливим використовувати цей масив, його розмір необхідно привести у відповідність з розміром масиву b. Для цього можна скористатися методом Resize об'єкту Array. Проте цей метод дозволяє змінювати кількість елементів такого масиву, для якого ця кількість вже визначена, тому перед викликом методу Resize створюється новий масив r, що складається з нуля елементів. Варто відзначити також те, що перед першим параметром методу Resize знаходиться ключове слово ref, що говорить про те, що даний метод приймає посилання на масив r, - саме тому усередині методу стає можливою зміна параметрів самого масиву, а не його копії.

Виклик методу можна здійснити таким чином:

Response.Write("Результати обчислення значень масиву:<br/>"); long [] result; int [] data={2,3,4,5}; Stepen(out result, 2, data); foreach (long i in result)Response.Write(i.ToString()+"<br/>");

Результат роботи програми зображений на рис. 3.9.

Мал. 3.9. Результат роботи методу, що підносить до заданого ступеня масив чисел

Підсумовуючи все сказане вище щодо методів, необхідно звернути увагу на наступне. Мова C# є об'єктно-орієнтованою мовою програмування. Як відомо, основну роль в таких мовах грають посилальні типи, тому коли методу передається об'єкт посилального типу, всі поля цього об'єкту можуть мінятися в методі, тобто програмний код методу може дістати повний доступ до всіх полів об'єкту. Це відбувається не дивлячись на те, що формально об'єкт не є вихідним і не має ключових слів ref і out, тобто використовує семантику виклику за значенням. При такому виклику саме посилання на об'єкт залишається незмінним, але стан об'єкту, значення його полів можуть повністю змінитися. Така ситуація достатньо поширена і є типовою, тому при роботі з посилальними типами даних ключові слова ref і out нечасто з'являються в описі аргументів методу.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: