8-bo‘lim
Metodlar
Metod e'lon qilish, parametr va qaytariladigan qiymat, ixtiyoriy va nomlangan argumentlar, ref, out va in, params, ortiqcha yuklash va lokal funksiyalar.
Ushbu bo‘lim mundarijasi
Metod - nom berilgan kod bo'lagi. U bir ishni bajaradi va kerak bo'lganda chaqiriladi. Kodni takrorlamaslikning asosiy vositasi.
Oddiy metod #
Salomlash("Husanboy");
Salomlash("Malika");
void Salomlash(string ism)
{
Console.WriteLine($"Assalomu alaykum, {ism}!");
}
Assalomu alaykum, Husanboy!
Assalomu alaykum, Malika!
Yuqori darajali ko'rsatmalarda metod lokal funksiya bo'ladi va uni e'lon qilinishidan oldin chaqirish mumkin.
Kompilyator butun faylni o'qib chiqadi, shuning uchun tartib muhim emas. Bu odatiy amaliyot: avval asosiy mantiq, pastda yordamchi metodlar.
Qiymat qaytaruvchi metod #
int natija = Qoshish(7, 5);
Console.WriteLine($"7 + 5 = {natija}");
Console.WriteLine($"Kvadrat: {Kvadrat(6)}");
int Qoshish(int a, int b)
{
return a + b;
}
int Kvadrat(int son) => son * son;
7 + 5 = 12
Kvadrat: 36
void - hech narsa qaytarmaydi. Boshqa har qanday tur - shu turdagi
qiymat qaytariladi.
Ikkinchi metod ifoda tanasi (=>) bilan yozilgan. Metod bitta
ifodadan iborat bo'lsa, bu qisqaroq va o'qish osonroq.
Ixtiyoriy parametrlar #
using System.Globalization;
Console.WriteLine(Hisobla(100));
Console.WriteLine(Hisobla(100, 0.2m));
Console.WriteLine(Hisobla(100, 0.2m, 10));
string Hisobla(decimal narx, decimal chegirma = 0.1m, decimal yetkazish = 0)
{
decimal yakuniy = narx * (1 - chegirma) + yetkazish;
return string.Format(CultureInfo.InvariantCulture,
"Narx {0}, chegirma {1:P0} -> {2}", narx, chegirma, yakuniy);
}
Narx 100, chegirma 10 % -> 90.0
Narx 100, chegirma 20 % -> 80.0
Narx 100, chegirma 20 % -> 90.0
Ixtiyoriy parametrlar oxirida turishi kerak - majburiylaridan keyin.
0.2 emas, 0.2mChaqiruvda 0.2m deb yozilganiga e'tibor bering. 0.2 o'z-o'zidan
double hisoblanadi va uni decimal parametrga berib bo'lmaydi:
error CS1503: Argument 2: cannot convert from 'double' to 'decimal'
Bu 3-bo'limdagi qoidaning amaldagi ko'rinishi: pul bilan ishlaganda
har bir kasr literaliga m qo'shing.
Nomlangan argumentlar #
Argument ko'p bo'lganda, nomini yozish kodni ancha tushunarli qiladi:
using System.Globalization;
Console.WriteLine(Hisobla(100, yetkazish: 15));
Console.WriteLine(Hisobla(narx: 200, chegirma: 0.25m));
string Hisobla(decimal narx, decimal chegirma = 0.1m, decimal yetkazish = 0)
{
decimal yakuniy = narx * (1 - chegirma) + yetkazish;
return string.Format(CultureInfo.InvariantCulture,
"Yakuniy: {0}", yakuniy);
}
Yakuniy: 105.0
Yakuniy: 150.00
Birinchi chaqiruvda chegirma o'tkazib yuborildi - u sukut qiymatini
oldi, yetkazish esa nom bilan berildi.
Chaqiruvga qarab ma'nosi tushunarsiz bo'lsa:
Yuborish("xat matni", true, false, true); // nima bu bayroqlar?
Yuborish("xat matni", shoshilinch: true, nusxa: false, saqlash: true);
Ikkinchi qator o'zini o'zi tushuntiradi. bool argumentlar uchun bu
deyarli har doim tavsiya etiladi.
ref, out va in #
Odatda argument nusxa bo'lib uzatiladi. Bu kalit so'zlar shuni o'zgartiradi.
out - metod natijani o'zgaruvchiga yozadi #
if (int.TryParse("42", out int son))
{
Console.WriteLine($"O'qildi: {son}");
}
Bolish(17, 5, out int butun, out int qoldiq);
Console.WriteLine($"17 / 5 = {butun}, qoldiq {qoldiq}");
void Bolish(int a, int b, out int natija, out int qoldiq)
{
natija = a / b;
qoldiq = a % b;
}
O'qildi: 42
17 / 5 = 3, qoldiq 2
out parametrga metod ichida albatta qiymat berilishi kerak -
aks holda kompilyator xato beradi.
ref - mavjud qiymatni o'zgartiradi #
int a = 5;
int b = 9;
Console.WriteLine($"Almashtirishdan oldin: a={a}, b={b}");
Almashtir(ref a, ref b);
Console.WriteLine($"Keyin: a={a}, b={b}");
void Almashtir(ref int x, ref int y)
{
(x, y) = (y, x);
}
Almashtirishdan oldin: a=5, b=9
Keyin: a=9, b=5
| Kalit so'z | Chaqirishdan oldin qiymat | Metod ichida |
|---|---|---|
| (yo'q) | Kerak | Nusxa o'zgaradi |
ref | Kerak | Aslini o'zgartiradi |
out | Kerak emas | Qiymat berish majburiy |
in | Kerak | O'zgartirib bo'lmaydi |
Ular kerakli vositalar, lekin kodni tushunish qiyinlashtiradi: metod chaqiruviga qarab o'zgaruvchingiz o'zgarib qolishi ko'rinmaydi.
Zamonaviy C# da ko'pincha yaxshiroq yechim bor:
- Bir nechta qiymat qaytarish kerakmi - kortej ishlating;
- "Bo'ldimi yoki yo'qmi" kerakmi -
boolqaytarib, natijanioutga yozing (buTryParseuslubi, u qabul qilingan).
Kortej bilan yuqoridagi bo'lish metodi ancha toza chiqadi.
Kortej qaytarish #
(int butun, int qoldiq) = Bolish(17, 5);
Console.WriteLine($"17 / 5 = {butun}, qoldiq {qoldiq}");
var natija = Bolish(20, 3);
Console.WriteLine($"20 / 3 = {natija.butun}, qoldiq {natija.qoldiq}");
(int butun, int qoldiq) Bolish(int a, int b) => (a / b, a % b);
17 / 5 = 3, qoldiq 2
20 / 3 = 6, qoldiq 2
Bu out dan ancha qulay: natija nomlangan, chaqiruv toza ko'rinadi.
params - istalgancha argument #
Console.WriteLine(Yigindi());
Console.WriteLine(Yigindi(5));
Console.WriteLine(Yigindi(1, 2, 3, 4, 5));
int Yigindi(params int[] sonlar)
{
int jami = 0;
foreach (int son in sonlar)
{
jami += son;
}
return jami;
}
0
5
15
Console.WriteLine ning o'zi ham shunday ishlaydi - shuning uchun unga
istalgancha argument berish mumkin.
Ortiqcha yuklash #
Bir xil nomli, lekin turli parametrli metodlar:
Console.WriteLine(Geometriya.Maydon(5));
Console.WriteLine(Geometriya.Maydon(4, 6));
Console.WriteLine(Geometriya.Maydon("kvadrat", 3));
static class Geometriya
{
public static int Maydon(int tomon) => tomon * tomon;
public static int Maydon(int eni, int boyi) => eni * boyi;
public static string Maydon(string nom, int tomon) =>
$"{nom}: {tomon * tomon}";
}
25
24
kvadrat: 9
Kompilyator argumentlarga qarab qaysi metodni chaqirishni o'zi aniqlaydi.
Yuqoridagi metodlar nega sinf ichiga qo'yildi? Chunki ularni shu bobdagi boshqa misollar kabi to'g'ridan-to'g'ri yozsangiz, kod kompilyatsiya qilinmaydi:
error CS0128: A local variable or function named 'Maydon'
is already defined in this scope
Ortiqcha yuklash faqat sinf a'zolari uchun ishlaydi. Lokal funksiyalar oddiy o'zgaruvchilar kabi qaraladi: bitta qamrovda bir xil nomli ikkita bo'la olmaydi.
Bu 1-bobda aytilgan gapning sababi: class va static shakli
eskirgani uchun emas, ba'zi imkoniyatlar faqat unda mavjudligi uchun
kerak. Sinflar bilan keyingi bobda to'liq tanishamiz.
Chiqarish.Yoz("salom");
static class Chiqarish
{
public static void Yoz(string matn) =>
Console.WriteLine($"A: {matn}");
public static void Yoz(string matn, bool qalin = false) =>
Console.WriteLine($"B: {matn}");
}
A: salom
Ikkala metod ham bitta argument bilan chaqirilishi mumkin. Kompilyator xato bermaydi - u aniqroq mos kelganini tanlaydi, ya'ni birinchisini.
Natijada siz ikkinchisini kutgan bo'lsangiz, buni topish juda qiyin. Shuning uchun ularni birga ishlatmaslikka harakat qiling.
Lokal funksiyalar #
Metod ichida yordamchi metod e'lon qilish mumkin:
Console.WriteLine(Faktorial(5));
Console.WriteLine(Faktorial(0));
int Faktorial(int n)
{
if (n < 0)
{
throw new ArgumentException("Manfiy son bo'lmasin", nameof(n));
}
return Hisobla(n);
// faqat shu metod ichida ko'rinadi
int Hisobla(int son) => son <= 1 ? 1 : son * Hisobla(son - 1);
}
120
1
Tashqi metod argumentni tekshiradi, ichkisi esa tekshiruvsiz rekursiya qiladi. Bu keng tarqalgan naqsh.
nameof nima qiladinameof(n) - o'zgaruvchi nomini satr sifatida beradi, ya'ni
"n".
Nega shunchaki "n" deb yozmaslik kerak? Chunki keyin parametr nomini
o'zgartirsangiz, nameof avtomatik yangilanadi, oddiy satr esa eski
nom bilan qolib ketadi va xato xabari chalg'ituvchi bo'ladi.
Metod nomlash qoidalari #
| Qoida | Misol |
|---|---|
| Katta harfdan boshlanadi (PascalCase) | HisoblaYigindi |
| Fe'l bilan boshlanadi | Yoz, Hisobla, Tekshir |
bool qaytarsa savol shaklida | BoshmiTekshir, MavjudmiTekshir |
| Parametrlar kichik harfdan (camelCase) | int talabaSoni |
Yaxshi metodning belgisi - nomini qiyinchiliksiz qo'ya olish.
Agar nom o'ylab topolmayotgan bo'lsangiz yoki nomda "va" so'zi paydo
bo'lsa (OqiVaSaqla), metod ikki ish qilyapti - uni ikkiga
bo'ling.
Uzunligi uchun qat'iy qoida yo'q, lekin ekranga sig'masa - bu ogohlantirish belgisi.
- Ikkita sonni qabul qilib, kattasini qaytaruvchi metod yozing.
- Uni ifoda tanasi (
=>) bilan qayta yozing. - Ixtiyoriy parametrli metod yarating va uni uch xil chaqiring.
- Nomlangan argument bilan chaqirib ko'ring.
outbilan bo'linma va qoldiqni qaytaruvchi metod yozing.- Xuddi shu metodni kortej bilan qayta yozing va solishtiring.
refbilan ikki o'zgaruvchi qiymatini almashtiring.paramsbilan istalgancha sonning o'rtachasini hisoblang.- Bir nomli uchta metodni turli parametrlar bilan yozing.
- Lokal funksiya bilan rekursiv Fibonachchi sonini hisoblang.
Xulosa #
- Metod bitta ish qilsin; nom qo'yish qiyin bo'lsa - uni bo'ling.
- Bitta ifodadan iborat metodni
=>bilan qisqartiring. - Ixtiyoriy parametrlar oxirida turadi; nomlangan argumentlar chaqiruvni tushunarli qiladi.
out- metod natijani yozadi,ref- mavjud qiymatni o'zgartiradi,in- o'zgartirishni taqiqlaydi.- Bir nechta qiymat qaytarish uchun
outemas, kortej qulayroq. paramsistalgancha argument qabul qiladi.- Ortiqcha yuklash va ixtiyoriy parametrni birga ishlatmang.
nameofnomni satrga aylantiradi va qayta nomlashda yangilanadi.
Keyingi bo'limda sinflar va obyektlarga o'tamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.