Natural type of Method group
Tags: csharp, news, features, dotnet
Published: 2024-05-30 05:30:38

Method group haqida qisqacha: 
Method group - bu bir xil nomga ega, ammo <u>parametrlari va qaytish turlari</u>(qisqacha sintaksis) bo'yicha farq qilishi mumkin bo'lgan funksiyalar to'plami. Method grouplar odatda delegatlar, hodisalar(event) va LINQ ifodalari bilan bog'liq vaziyatlarda qo'llaniladi. Batafsil malumot -> [link](https://dev.to/farkhadk/c-dagi-method-overload-va-method-group-3p7k).

C# tilidagi method group _natural type_(tabiy turi) kompilyator tomonidan  guruh ichidagi methodlar sintaksiga mos keladigan delegat turiga ishora qiladi. C#-dagi _natural type_ method guruhlarini ishlatish jarayonini soddalashtiradi, delegatlarni talab qiladigan kontekstlarda metod guruhlarini to'g'ridan-to'g'ri va yashirin foydalanishga imkon berish orqali kodni o'qish va samaradorlikni oshiradi. Bu, ayniqsa, LINQ so'rovlari va hodisa(event)larni boshqarish bilan bog'liq stsenariylarda foydalidir. Qisqa qilib aytganda _natural type_(tabiy tur) kompilyator tomonidan yashirincha delegatga o'giriladi, delegatlar esa o'z vaqtida, o'zining shartlarini qoniqtirgan funksiyani overloadini method groupdan tanlab oladi. Yaniy bu feature(natural type) delegatlarni ochiqchasiga(explecitly) yaratishga xojat qoldirmaydi, kontekstga qarab kompilyator o'zi yaratadi.

Delegatlar qanday ishlashini tushunish uchun kichik bir misol:
```C#
Action<string> writeLineString = Console.WriteLine;
writeLineString("Hello, World!");
// output -> Hello, World!
```
Birinchi qatorda `writeLineString` _delegati_ yaratildi, va unga `WriteLine` method group o'zlashtirdi. Keyingi qatorda `writeLineString` delegatiga `string` malumot tipni argument sifatida joylandi, chunki bizning(kontekstda) delegatni sharti, faqat string qabul qiladigon funksiyalarni talab qiladi(`Action<string>`). Kompilyatorni o'zi delegatdan foydalanib, `WriteLine` guruhidan kerakli overloadni topib ishga tushiradi. Qisqacha delegatlar qanday ishlashi haqidaham tushib oldik
 
Endi esa C# da natural type tushunchasi kirib kelamagunicha bolgan holat:
```C#
var numbers = new[] { 1, 2, 3, 4, 5 };

Func<int, bool> isEvendelegate = IsEven;
var evenNumbers = numbers.Where(isEvendelegate).ToList();
Action<int> writeLineInt = Console.WriteLine;

Console.WriteLine("Even numbers:");
foreach (var num in evenNumbers)
    writeLineInt(num);

static bool IsEven(int number) => number % 2 == 0;
```
Output
```
Even numbers:
2
4
```
> `Func<int, bool>` xuddi `Action<string>` kabi ishlaydi, lekin biroz farq qiladi. Func<T1,T2> T1 delegatimizga o'zlashtiriladigon method groupga keladigon argument tipi, T2 esa shu methodimiz qaytaradigon malumot turi. `Action<T>` esa harqanday `void` qaytaradigon lekin `T` qabul qiladigon method guruhlar uchun ishlatiladi.

Kodda ko'rganimizdek numbers array bor(1dan 5gacha qiymatlari bilan), `isEvenDelegati` vakili(delegati) `int` type qabul qiluvchi va `bool` qaytarubchi method groupni qabul qiladi, bu shartni esa `IsEven` methodi qiniqtiradi, shung uchun ushbu metodni delegatimizga o'zlashtirdik. Keyingi qatorda _LINQ_ funksiyalaridan bolmish `Where()` metodini delegatimiz unga argument qilib chaqirdik, bu metod esa faqatgina _juft_ sonlardan tashkil topgan arrayni `evenNumbers` o'zgaruvchisiga o'zlashtirdi. Etibor qilgan bolsangiz birinchi misolimizdan ozgina farq qiladigon ko'dniham ishlatdik.

Endi esa huddi o'sha kodni faqat natural type bilan modify qilamiz:
```C#
var numbers = new[] { 1, 2, 3, 4, 5 };

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

Console.WriteLine("Even numbers:");
evenNumbers.ForEach(Console.WriteLine);


bool IsEven(int number) => number % 2 == 0;
```
Output
```
Even numbers:
2
4
```
Ushbu misolimizda ko'rishingiz mumkin hechqanday `Func<T1,T2>` yoki `Action<T>` delegatlari yoq. Delegatlarni o'rniga tog'ridan to'g'ri method groupni ishlatdik, va natija esa birxil. Yana bir etibor qilishimiz kerak bolgan joyi, `Where()` funksiyasi bu safar `ToList()` qaytardi, bunday qilishga sabab, `ForEach()` metodi faqat list uchun ishlaydi, va bu funksiyaga `Console.WriteLine` method groupini delegat ishlatmasdan yubordik. 

Aslida bu funksianal "_natural type_" C# da ~ 10 versiyadan beri bor, lekin o'sha damlardan beri bu optimal emas edi, yaniy kompilyator har bir methodga alohida qarab chiqar edi, hatto bazi funksiyala ochiqchasiga delegat shartini qoniqtirmasaham(boshqa tiplar qabul qilsaham, ko'proq yoki ozroq argumentlar soni bolsaham).
C# 13 da _natural typeni_ ishlash prinsipini to'g'irlandi, endi kompilyator *scope ichidagi tog'ri kelmagan methodlarni tashlab yuboradi.
Agar methodlar generic bolsa yoki yetlicha/ortiqcha argumentlar soni. Agar kerakli method ushbu scopeda topilmasa, qidiruv kelgusi scope ga o'tadi, taqdim etilgan scopelardan birontasida kerakli shartni qoniqtira oladigon methodni topa olmasa, method group natural type-ga ega emas deb hisoblanadi, va compile-time error otadi. Oddiy qilib aytganda, kompilyator endi barcha mumkin bo'lgan methodlarni oldindan ko'rib chiqish o'rniga, har bir scope-ni tekshirganda, qo'llanilmaydigan/keraksiz methodlarni darhol chiqarib tashlash orqali method guruhidan qaysi overloaddan foydalanishni samaraliroq aniqlaydi. Bu esa o'z vaqtida jarayonni tezlashtiradi.

> _scope_ deb methodlar implement qilinga kontekstni class, import qilingan namespace larni nazarda tudadi.