17-bo‘lim

Delegatlar, lambda va hodisalar

Delegate bilan funksiyani o'zgaruvchida saqlash, Func va Action, bir va ko'p qatorli lambda, Event va AddHandler.

🕑 11 daqiqa o‘qish 📄 519 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Delegate
  2. Func va Action
  3. Lambda - nomsiz funksiya
  4. Ko'p qatorli lambda
  5. Funksiyani parametr sifatida uzatish
  6. Lambda tashqi o'zgaruvchini ko'radi
  7. Hodisalar
  8. Bir necha tinglovchi
  9. Xulosa

Shu paytgacha o'zgaruvchilarda son va matn saqladik. Aslida funksiyaning o'zini ham saqlash mumkin.

Delegate #

VB
Public Delegate Function Amal(a As Integer, b As Integer) As Integer

Module Dastur
    Function Qoshish(a As Integer, b As Integer) As Integer
        Return a + b
    End Function

    Function Kopaytirish(a As Integer, b As Integer) As Integer
        Return a * b
    End Function

    Sub Main()
        Dim bajar As Amal

        bajar = AddressOf Qoshish
        Console.WriteLine(bajar(6, 7))

        bajar = AddressOf Kopaytirish
        Console.WriteLine(bajar(6, 7))
    End Sub
End Module
Natija
13
42

Delegate - funksiyaning shakli: qanday parametr oladi va nima qaytaradi. AddressOf esa aniq funksiyaga ishora beradi.

Func va Action #

Har safar Delegate e'lon qilish shart emas - .NET da tayyorlari bor:

VB
Module Dastur
    Sub Main()
        Dim kvadrat As Func(Of Integer, Integer) = Function(x) x * x
        Dim yigindi As Func(Of Integer, Integer, Integer) =
            Function(a, b) a + b
        Dim chiqar As Action(Of String) =
            Sub(matn) Console.WriteLine($">> {matn}")

        Console.WriteLine(kvadrat(9))
        Console.WriteLine(yigindi(15, 27))
        chiqar("salom")
    End Sub
End Module
Natija
81
42
>> salom
TurQiymat qaytaradimiMisol
Func(Of A, Natija)Ha - oxirgisi natija turiFunc(Of Integer, String)
Action(Of A)Yo'qAction(Of String)
Func da oxirgi tur - natija

Func(Of Integer, Integer, String) - bu ikkita Integer oladi va String qaytaradi degani.

Ya'ni oxirgi tur har doim natija. Buni bilmasdan ko'p adashadilar.

Action esa hech narsa qaytarmaydi, shuning uchun undagi hamma tur - parametr.

Lambda - nomsiz funksiya #

VB
Module Dastur
    Sub Main()
        Dim sonlar() As Integer = {5, 12, 8, 23, 16}

        Dim juftlar = sonlar.Where(Function(s) s Mod 2 = 0)
        Console.WriteLine(String.Join(", ", juftlar))

        Dim ikkilangan = sonlar.Select(Function(s) s * 2)
        Console.WriteLine(String.Join(", ", ikkilangan))

        Dim jami = sonlar.Sum(Function(s) s)
        Console.WriteLine(jami)
    End Sub
End Module
Natija
12, 8, 16
10, 24, 16, 46, 32
64

Function(s) s Mod 2 = 0 - "s ni ol, juftmi deb tekshir" degan kichik funksiya. Uni alohida e'lon qilish shart emas.

Ko'p qatorli lambda #

VB
Module Dastur
    Sub Main()
        Dim baho As Func(Of Integer, String) =
            Function(ball)
                If ball >= 90 Then
                    Return "A'lo"
                ElseIf ball >= 70 Then
                    Return "Yaxshi"
                Else
                    Return "Qoniqarsiz"
                End If
            End Function

        For Each b As Integer In New Integer() {95, 78, 55}
            Console.WriteLine($"{b} -> {baho(b)}")
        Next
    End Sub
End Module
Natija
95 -> A'lo
78 -> Yaxshi
55 -> Qoniqarsiz

Bir qatorga sig'masa, Function(...) dan keyin yangi qatorga o'tib, End Function bilan yopiladi.

Funksiyani parametr sifatida uzatish #

VB
Module Dastur
    Sub Ishlov(sonlar() As Integer, qoida As Func(Of Integer, Boolean),
               nom As String)
        Dim mos = sonlar.Where(qoida)
        Console.WriteLine($"{nom}: {String.Join(", ", mos)}")
    End Sub

    Sub Main()
        Dim sonlar() As Integer = {4, 17, 8, 23, 15, 42}

        Ishlov(sonlar, Function(s) s Mod 2 = 0, "Juftlar")
        Ishlov(sonlar, Function(s) s > 20, "Yiriklar")
        Ishlov(sonlar, Function(s) s < 10, "Kichiklar")
    End Sub
End Module
Natija
Juftlar: 4, 8, 42
Yiriklar: 23, 42
Kichiklar: 4, 8

Bitta Ishlov protsedurasi - uchta turli qoida. Mantiqni tashqaridan berish katta moslashuvchanlik beradi.

Lambda tashqi o'zgaruvchini ko'radi #

VB
Module Dastur
    Sub Main()
        Dim chegara As Integer = 10
        Dim sonlar() As Integer = {4, 17, 8, 23}

        Dim tekshir As Func(Of Integer, Boolean) = Function(s) s > chegara
        Console.WriteLine(String.Join(", ", sonlar.Where(tekshir)))

        chegara = 20
        Console.WriteLine(String.Join(", ", sonlar.Where(tekshir)))
    End Sub
End Module
Natija
17, 23
23

Lambda chegara ning qiymatini emas, o'zini eslab qoldi. U o'zgargach, lambda ham boshqacha ishladi. Bu yopilma (closure) deb ataladi.

Yopilma siklda kutilmagan natija berishi mumkin

Sikl o'zgaruvchisini lambda ichida ishlatsangiz, hamma lambda oxirgi qiymatni ko'rishi mumkin.

Xavfsiz yo'l - sikl ichida nusxa olish:

VB
For i As Integer = 1 To 3
    Dim nusxa As Integer = i
    amallar.Add(Function() nusxa * 10)
Next

Shunda har bir lambda o'z nusxasini eslab qoladi.

Hodisalar #

Hodisa - "biror narsa sodir bo'ldi" degan xabar. Uni kim eshitishini sinf bilmaydi.

VB
Public Class Hisob
    Public Event QoldiqKamaydi(qoldiq As Decimal)

    Private _qoldiq As Decimal

    Public Sub New(boshlangich As Decimal)
        _qoldiq = boshlangich
    End Sub

    Public Sub Yechish(summa As Decimal)
        _qoldiq -= summa
        Console.WriteLine($"Yechildi: {summa}, qoldiq: {_qoldiq}")

        If _qoldiq < 100000D Then
            RaiseEvent QoldiqKamaydi(_qoldiq)
        End If
    End Sub
End Class

Module Dastur
    Sub Ogohlantir(qoldiq As Decimal)
        Console.WriteLine($"  DIQQAT: qoldiq juda kam - {qoldiq}")
    End Sub

    Sub Main()
        Dim h As New Hisob(500000D)
        AddHandler h.QoldiqKamaydi, AddressOf Ogohlantir

        h.Yechish(200000D)
        h.Yechish(250000D)
    End Sub
End Module
Natija
Yechildi: 200000, qoldiq: 300000
Yechildi: 250000, qoldiq: 50000
  DIQQAT: qoldiq juda kam - 50000
Kalit so'zVazifasi
EventHodisani e'lon qiladi
RaiseEventHodisani chaqiradi
AddHandlerTinglovchi qo'shadi
RemoveHandlerTinglovchini olib tashlaydi

Bir necha tinglovchi #

VB
Public Class Tugma
    Public Event Bosildi(nom As String)

    Public Property Nom As String

    Public Sub New(nom As String)
        Me.Nom = nom
    End Sub

    Public Sub Bosish()
        RaiseEvent Bosildi(Nom)
    End Sub
End Class

Module Dastur
    Sub Main()
        Dim t As New Tugma("Saqlash")

        AddHandler t.Bosildi,
            Sub(nom) Console.WriteLine($"Jurnal: {nom} bosildi")
        AddHandler t.Bosildi,
            Sub(nom) Console.WriteLine($"Ekran: {nom} ishga tushdi")

        t.Bosish()
    End Sub
End Module
Natija
Jurnal: Saqlash bosildi
Ekran: Saqlash ishga tushdi

Bitta hodisaga bir nechta tinglovchi qo'shilishi mumkin va ular qo'shilgan tartibda chaqiriladi.

Hodisalar nima uchun kerak

Ular kodni bir-biridan ajratadi.

Hisob sinfi jurnal, ekran yoki elektron pochta haqida hech narsa bilmaydi. U faqat "qoldiq kamaydi" deb e'lon qiladi. Kim eshitishi va nima qilishi - butunlay boshqa masala.

Shu sababli yangi xatti-harakat qo'shish uchun Hisob sinfiga tegish kerak emas - shunchaki yangi tinglovchi qo'shiladi.

Amaliy topshiriq
  1. Ikkita sonni ayiradigan funksiyani Delegate orqali chaqiring.
  2. Func(Of Double, Double) bilan kvadrat ildiz hisoblang.
  3. Action(Of String) bilan matnni katta harfda chiqaring.
  4. Lambda bilan ro'yxatdan 5 dan kichik sonlarni ajrating.
  5. Ko'p qatorli lambda yozib, unda If ishlating.
  6. Filtrlash qoidasini parametr sifatida uzatadigan protsedura yozing.
  7. Yopilmani sinab ko'ring: tashqi o'zgaruvchini o'zgartiring.
  8. Harorat sinfiga JudaIssiq hodisasini qo'shing.
  9. Bitta hodisaga ikkita tinglovchi ulang.
  10. RemoveHandler bilan tinglovchini olib tashlang.

Xulosa #

  • Delegate - funksiyaning shakli; AddressOf aniq funksiyaga ishora qiladi.
  • Func(Of ..., Natija) qiymat qaytaradi - oxirgi tur natija; Action(Of ...) qaytarmaydi.
  • Lambda - nomsiz funksiya: Function(x) x * 2.
  • Ko'p qatorli lambda End Function bilan yopiladi.
  • Funksiyani parametr sifatida uzatib, bitta protsedurani ko'p maqsadda ishlatish mumkin.
  • Yopilma: lambda tashqi o'zgaruvchining o'zini eslab qoladi - siklda nusxa oling.
  • Event + RaiseEvent + AddHandler sinflarni bir-biridan ajratadi.

Keyingi bo'limda generiklar va Nothing xavfsizligini ko'ramiz.

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.