1. Giriş
Proqram yazarkən bəzən yalnız bir dəfə istifadə olunacaq sadə bir əməliyyatı təsvir etmək lazım gəlir. Bunun üçün ayrıca metod yaratmaq - hazır dəstdən təyyarə yığmaq üçün çəkic götürüb, mismarı çalmaq kimidir. Daha asandır - mövcud şeylə işi “yerində” həll etmək.
Anonim metod - adı olmayan, çünki yarandığı yerdə istifadə olunan müvəqqəti kod parçasıdır. O:
- Başqa bir metod daxilində elan olunur.
- Adı yoxdur.
- Adətən bir dəfə istifadə olunur - məsələn, delegate-ə ötürülür və ya event-ə qoşulur.
Bu günlərdə daha çox lambda ifadələri (operator =>) istifadə olunur, amma anonim metodları başa düşmək delegate-lərin və C#-ın event modelinin necə qurulduğunu anlamağa kömək edir.
Anonim metod nə vaxt faydalıdır?
- Logic-in bir parçacığını tezcə parametrlə ötürmək lazımdır, məsələn sort, filter, event və s.
- Bir dəfəlik logic üçün sinifdə çoxlu ayrıca metodlar yaratmaq məntiqli deyil.
- Kodun kompakt və oxunaqlı olmasını istəyirsinizsə: bütün “kiçik biznes-logic” bir yerdədir.
Qısa tarixçə
C#-də anonim metod yaratmaq imkanı ilk dəfə 2.0 versiyasında ortaya çıxdı. Ondan əvvəl delegate-lərlə işləmək daha səliqəsiz idi: hətta bir yerdə istifadə olunacaq logic üçün də ayrıca adlandırılmış metod yazmalı idin. Anonim metodlar gələndən sonra iş sadələşdi, lambda ifadələrinin gəlməsi ilə isə bu ideya daha da qısa-yoldan istifadəyə çevrildi.
2. Janrın klassikası: delegate-lər və adi “adlandırılmış” metod
Anonim metodlarla tanış olmadan əvvəl delegate vasitəsilə davranışı ötürməyin standart yolunu xatırlayaq. Məsələn, “Kitab bazası” tətbiqimiz var və biz kitabları müxtəlif meyarlara görə filterləmək istəyirik.
// Delegate-i elan edirik
public delegate bool BookFilter(Book book);
// Kitab sinfi
public class Book
{
public string Title { get; set; }
public int Year { get; set; }
}
Əvvəllər belə yazırdıq:
// Ayrı filter funksiyası
public static bool IsClassic(Book b)
{
return b.Year < 1970;
}
// Haradasa tətbiqdə
BookFilter filter = IsClassic;
Hər dəfə ayrıca metod açmaq həmişə rahat deyil. Əgər filter-lər onlarla ölçülürsə?
3. Anonim metod: minimalizm, delegate-lərlə dostluq
Anonim metod kod-filter-i lazım olan yerdə birbaşa təyin etməyə imkan verir:
BookFilter filter = delegate(Book b)
{
return b.Year < 1970;
};
Budur hamısı! Heç bir əlavə metod yoxdur, bütün funksiya yerindədir. delegate adlandırılmamış funksiyanın elan olunması kimi çıxış edir.
Ümumi sintaksis
delegate([argumentlər])
{
// metodun gövdəsi
};
Proqram daxilinə örnək:
public class Book
{
public string Title { get; set; }
public int Year { get; set; }
}
public delegate bool BookFilter(Book book);
class Program
{
static void Main()
{
Book[] books = {
new Book { Title = "Master i Margarita", Year = 1967 },
new Book { Title = "Clean Code", Year = 2008 }
};
// Klasiklər üçün anonim filter
BookFilter filter = delegate(Book b)
{
return b.Year < 1970;
};
foreach (Book book in books)
{
if (filter(book)) // anonim funksiyanı çağırırıq!
Console.WriteLine($"{book.Title} — klassika!");
}
}
}
Çıxış:
Master i Margarita — klassika!
4. Müxtəlif delegate-lərlə anonim metod
Anonim metodlar bütün delegate-lərlə yaxşı işləyir. Məsələn, standart Action və Func<T, TResult>, onları daha sonra detallı öyrənəcəyik.
Action<string> sayHello = delegate(string name)
{
Console.WriteLine($"Salam, {name}!");
};
sayHello("Dunya"); // Salam, Dunya!
Qısa illustrasiya: “birdəfəlik” anonim metod necə işləyir
Anonim metodu müvəqqəti işçi kimi təsəvvür etmək asandır: qısa tapşırıq üçün gəlir, yerinə yetirir və gedir. İşçi ilə tapşırığı delegate vasitəsilə bağlayırıq.
Func<int, int, int> sum = delegate (int a, int b) {
return a + b;
};
Console.WriteLine(sum(5, 7)); // 12
Tətbiq: sort, axtarış, kolleksiyaların emalı
Tutaq ki, kitablar siyahımız var və biz onları nəşr ilinə görə sort etmək istəyirik. Bir dəfəlik müqayisə üçün ayrıca metod elan etmək artıqdır.
var books = new List<Book>
{
new Book { Title = "Master i Margarita", Year = 1967 },
new Book { Title = "Clean Code", Year = 2008 }
};
books.Sort(delegate(Book a, Book b)
{
return a.Year.CompareTo(b.Year);
});
foreach (var book in books)
Console.WriteLine($"{book.Title} ({book.Year})");
5. Faydalı nüanslar
Anonim metod lambda ifadəsi ilə eyni deyil?
Müasir C#-da daha çox lambda ifadələri (=>) istifadə olunur və adətən aralarında az fərq var, amma əsas fərqlər mövcuddur:
- Lambda ifadələri daha qısa və ifadəlidir.
- Lambda-larda dəyişənlərin tutulması üçün aydın qaydalar var (bunu sonra öyrənəcəyik).
- Anonim metodlar əvvəl çıxdı və köhnə layihələrdə bəzən qalır.
Məsələn, bizim nümunə lambda ilə belə görünərdi:
BookFilter filter = b => b.Year < 1970;
Amma həm köhnə sintaksisi, həm də yeni sintaksisi bildikdə müsahibələrdə, başqasının kodunu oxuyanda və delegate-ləri dərin anlamaq üçün faydalıdır.
Parametrləri olan və olmayan anonim metod
Əgər delegate heç nə qəbul etmirsə, bir sətrdə yaza bilərsiniz:
Action printHello = delegate { Console.WriteLine("Salam!"); };
printHello(); // Salam!
Əgər parametr qəbul edirsə — yenə də bir sətrdə yazmaq olar:
Action<int> printSquare = delegate (int x) { Console.WriteLine(x * x); };
printSquare(6); // 36
Anonim metod və Lambda-ifadə
| Anonim metod | Lambda-ifadə | |
|---|---|---|
| Sintaksis | |
|
| Dəyişənlərin tutulması | Bəli | Bəli |
| Populyarlıq | Nadir istifadə olunur | Standart |
| Qaytarma dəyəri | Bəli/övlad | Bəli/övlad |
| Çoxsətirlilik | Bəli | Bəli |
6. Anonim metodlar — kiçik məqamlar və istifadə nüansları
Local dəyişənlərin tutulması
Anonim metodlar əhatə edən metodun dəyişənlərini istifadə edə bilər — bu mexanizm “closure” adlanır. Məsələn:
int minYear = 1970;
BookFilter filter = delegate(Book book)
{
return book.Year < minYear;
};
Console.WriteLine(filter(new Book { Title = "Test", Year = 1960 })); // True
Əgər sonra minYear-i dəyişsəniz, filter yeni dəyəri istifadə edəcək!
Parametrləri göstərməyə ehtiyac yoxdur
Parametrlər lazım deyilsə:
Action sayHi = delegate { Console.WriteLine("Hi!"); };
null ötürülməsi
Əgər delegate-ə heç bir metod təyin edilməyibsə (məsələn anonim yoxdursa), onun dəyəri — null olur və çağırış NullReferenceException-a səbəb olacaq. Diqqətli olun.
Çoxsətirlilik
Anonim metod tam blok kodu, şərtlər, dövrlər və digər çağırışlar ola bilər:
Action manyThings = delegate
{
Console.WriteLine("Başladıq!");
for (int i = 0; i < 3; i++)
Console.WriteLine(i);
Console.WriteLine("Bitirdik!");
};
manyThings();
7. Tipik səhvlər və özəlliklər
Bəzən proqramçılar dəyişənlərin scope-unı çaşdırırlar: dövrdən və ya nested metoddan tutulmuş dəyərlər gözlənilməz nəticələr verə bilər.
List<Action> actions = new List<Action>();
for (int i = 0; i < 3; i++)
{
actions.Add(delegate { Console.WriteLine(i); });
}
foreach (var action in actions) action(); // 3 3 3 — sürpriz!
Səbəb odur ki, anonim metod i dəyişənini “görür” — dövr bitdikdə i 3-ə bərabər oldu. Bütün metodlar eyni şeyi yazdırır. Düz davranış üçün dəyişəni belə tutmaq yaxşıdır:
for (int i = 0; i < 3; i++)
{
int current = i;
actions.Add(delegate { Console.WriteLine(current); });
}
GO TO FULL VERSION