C# dagi Method overload va Method group.
Tags: csharp, dotnet, features
Published: 2024-05-30 00:51:59

Method group va Method overload tushunchalarni farqlash uchun `event`, `delegate` yoki `LINQ`, shulardan hech bolmaganda kamida bir donasini bilish tavsiya qilinadi. Bu feature(xususiyat)lar, dasturchilarga bir vaqtning o'zida bir xil **nomli** birnechta methodlarni yaratishga imkon beradi. Ushbu o'xshash nomli methodlarni bir biridan farqi, ular **qaytaradigon** malumot tiplari hamda **qabul qiluvchi** argumentlar soni bir-biridan farq qilishidadur. Qishqacha qilib aytganda birxil ish bacharuvchi methodlarni bir **nom** ostida jamlash uchun ishlatilinadi.

> NOTE: bu ikkala feature/tushuncha bir-biriga uzviy bog'liq!

Misol tariqasida Add() methodini yaratamiz:

```C#
static int Add(int a, int b) => a + b;
static long Add(long a, long b) => a + b;
static double Add(double a, double b) => a + b;
    
private static void Main(string[] args)
{
   int i = 1, j = 2;
   var sumOfInt = Add(i, j);
   Console.WriteLine($"Intlar summasi: {sumOfInt}");
        
   long l = 10, m = 20;
   var sumOfLong = Add(l, m);
   Console.WriteLine($"Longlar summasi: {sumOfLong}");

   double d = 1.102, s = 3.14;
   var sumOfDouble = Add(d, s);
   Console.WriteLine($"Doublelar summasi: {sumOfDouble}");
}
```
Output: 
```
Intlar summasi: 3
Longlar summasi: 30
Doublelar summasi: 4.242
```

> Yuqorida keltirilga ko'd asosan **Metod overload** tushunchasiga to'gri keladi, lekin **method group** sintaksisiham huddi shunday. Ularni farqi haqida sal pastroqda gaplashamiz.

Uchala `Add()` methodimizga etibor bersangiz, ular qabul qilayotgan argumentlar hamda, o'sha argumentlar ustida o'tqazilgan operatsiyadan so'ng qaytarishi kerak bolgan malumot turi(return type) bir biridan farq qiladi. C# kompilyatori shunchali aqillikiy, kelayotgan argument turiga asoslanib kerakli bolgan methodni o'zi chaqirib xisob kitobni amalga oshiradi. 

Yana bir yaqqol misol tariqasida biz bilgan `Console` klasidan keluvchi `WriteLine()` methodini aytishimiz mumkin, har bir overloadi(nusxasi) `void` qaytargani bilan, methodlarni qabul qiluvchi argumentlar soni va ularni turlari har-hil. Qo'shimcha qilib aytamanki har kim o'z xo'xshiga ko'ra koplab kombinatsiyalarni amalga oshirishi mumkin, demoqchi bolganim method qaytaradigon type qolgan overloadlarinikiga o'xshash bolsaxam, qabul qiladigon typelar soni va turlari farq qilsa bolgani ishlayveradi. Shu jumladan teskarisigaham ishlayveradi, argumentlar birhil bolsada qatrariladigon tur boshqacha bolsa overload hisoblanadi. Lekin extiyot bo'lish zarur!!! 

> Method/funksiyalar qanday va qaysi payt ishga tushishi xaqida biroz tushuncha olsak: Harqanday methodga murojat qilinganda i.e. `WriteLine` agar `()` qavslarni qo'yilmasa bu funksiyamiz _ishga tushmaydi_. Yaniy `()` qavslari bor method kod run bolganida navbat o'sha funksiyaga kelishi bilanoq ishaga tushadi. Albatta bu tushuntirish abstrakt bolib toliq va mutloq to'g'ri bolgan misol emas. Lekin oz bolsada xaqiqatga yaqin.

Endi **method group** ga to'xtaladigon bolsak, postni cho'zib kod bilan misollarni keltirib o'tirmayman. Qisqacha qilib aytganda method group hamda method overload implementation(yaratilishi)ni syntaksisi birxil. Lekin bu ikkala tushunchani ishlatilish jarayoni va maqsadlari turlicha.


Method overload hamda method group qayerda va qanday ishlashi haqida batafsil gaplashsak.


Method overload - asosan kodni o'qish/tushunish uchun hamda eslab qolish uchun osonroq qiladigon feature xisoblanadi, yuqorida keltirilgan ko'dga yuzlansak, C# da agar overload qilish xususiyati bolmaganda harbir tip uchun boshqa boshqa _nom_ o'ylab topish va uni qanday ish bajarishini yodda tutishimiz kerak bolar edi. Misol uchun `int` type uchun `IntAdd(...)`, `double` uchun esa `DoubleAdd(...)` va hokazo. Overload qilingan methodlar turgan class filega yangiliklar kiritilganda, shu yangiliklarni handle(qayta ishlash) qilish uchun yana bir overload qo'shilsa bas. API lar yaratilganidaham juda qo'l kelishi mumkin.

Method groupni esa ko'pincha methodni _darhol_ chaqirmasdan, uning **nomi**ga gina murojaat qilib eventlarni handle qilish(qayta ishlash) hamda methodlarni parametrlar (delegatlar) sifatida o'tkazishda va LINQ expression(iboralari)ni islatilyotkanida foydalidur. Aniqroq qilib aytganda kod yozish paytida kerakli bolgan methodni nominigina yozib ketiladi va kod **runtime**(ishga tushgan)paytda, chaqiriladigan methodni keyinroq aniqlanashga imkon beradi. Bundan nima naf?! Yuqorida aytganimizdek methodlarni chaqirishimiz bilanoq ular ishga tushib keradi, bazi holatlarda esa bu narsa ko'dimizni flexibility(moslashuvchanlik)ga tasir ko'rsatadi. Misol uchun assinxron dastur tuzganimizda, dasturimiz ishga tushishi bilanoq, methodlarni o'sha zaxoti ishga tushishi, bizni dastur uchun ajratilgan resurslar(xotira)ni egallab qo'yishi, va bu o'z vaqtida hatoliklar yoki, xisob-kitobda kutilmagan natijalarga olib kelishi mumkin.

Misol:

```C#
// delegat
Action<string> writeLineString = Console.WriteLine; 
writeLineString("Hello, World!"); 
```
 Birinchi qatorda `delegate` method groupdagi nomga ishora qiladi, lekin delegat turiga qarab maxsus overloadini chaqiradi, delegatimizda argument sifatiga `string`ni belgilaganmiz shuning uchun _runtime_ paytida _kompilyator_ `WriteLine()` methodini argument sifatida stringni oladigon overloadini chaqiradi. 
> Method group ishlash prinsipi method overloadnikiga o'xshash.

Endi **LINQ** bilan misolni ko'rib chiqsak:

```C#
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };

var evenNumbers = numbers.Where(IsEven).ToList();

evenNumbers.ForEach(Console.WriteLine); 

static bool IsEven(int number) => number % 2 == 0;
```
> Bu code-da method group faqat `IsEven` funksiyasidan tashkil topgan, yaniy har-doimham qo'shimcha `IsEven` overloadi bo'lishi shart emas, method group deb bir dona methodniham aytsa boladi. 

Kodmizda 1dan 5gacha bolgan list bor, va biz keyingi qatorga LINQ ni ishlatgan holda IsEven funksiyasini faqatgina nomini argument sifatida yuborib, faqat juft bo'lgan sonlar listini yaratyapmiz. IsEven funksiyasini agar `()` bilan chaqirsak bizning kod hatolik chiqaradi, chunki yuqorida aytilganidek `()` bilan chaqirilgan methodlar o'sha zahotiyoq ishga tushib ketadi. 3-chi qatorga etibor bersangiz `ForEach()` methodi `WriteLine` funksiyaniham faqatginaham method group nomiga murojat qilyapti, va kompilyator `int` type qabul qiladigon `WriteLine` overloadini chaqirib, sonlarni konsolga chiqarmoqda. 

Method Group ga aloqador yana bir etiborga loyiq mavzu bor, uning nomi _Method Group Natural Type_ bu mavzu xaqida esa boshqa [postimda](https://dev.to/farkhadk/natural-type-of-method-group-min) gaplashamiz. 

Etibor uchun raxmat.