CodeGym /Kurslar /C# SELF /Anonim metodlarla tanışlıq ( ...

Anonim metodlarla tanışlıq ( delegate)

C# SELF
Səviyyə , Dərs
Mövcuddur

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 ActionFunc<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
delegate (...) {}
(args) => {}
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); });
}
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION