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.
Ushbu bo‘lim mundarijasi
Shu paytgacha o'zgaruvchilarda son va matn saqladik. Aslida funksiyaning o'zini ham saqlash mumkin.
Delegate #
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
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:
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
81
42
>> salom
| Tur | Qiymat qaytaradimi | Misol |
|---|---|---|
Func(Of A, Natija) | Ha - oxirgisi natija turi | Func(Of Integer, String) |
Action(Of A) | Yo'q | Action(Of String) |
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 #
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
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 #
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
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 #
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
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 #
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
17, 23
23
Lambda chegara ning qiymatini emas, o'zini eslab qoldi. U
o'zgargach, lambda ham boshqacha ishladi. Bu yopilma (closure)
deb ataladi.
Sikl o'zgaruvchisini lambda ichida ishlatsangiz, hamma lambda oxirgi qiymatni ko'rishi mumkin.
Xavfsiz yo'l - sikl ichida nusxa olish:
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.
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
Yechildi: 200000, qoldiq: 300000
Yechildi: 250000, qoldiq: 50000
DIQQAT: qoldiq juda kam - 50000
| Kalit so'z | Vazifasi |
|---|---|
Event | Hodisani e'lon qiladi |
RaiseEvent | Hodisani chaqiradi |
AddHandler | Tinglovchi qo'shadi |
RemoveHandler | Tinglovchini olib tashlaydi |
Bir necha tinglovchi #
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
Jurnal: Saqlash bosildi
Ekran: Saqlash ishga tushdi
Bitta hodisaga bir nechta tinglovchi qo'shilishi mumkin va ular qo'shilgan tartibda chaqiriladi.
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.
- Ikkita sonni ayiradigan funksiyani
Delegateorqali chaqiring. Func(Of Double, Double)bilan kvadrat ildiz hisoblang.Action(Of String)bilan matnni katta harfda chiqaring.- Lambda bilan ro'yxatdan 5 dan kichik sonlarni ajrating.
- Ko'p qatorli lambda yozib, unda
Ifishlating. - Filtrlash qoidasini parametr sifatida uzatadigan protsedura yozing.
- Yopilmani sinab ko'ring: tashqi o'zgaruvchini o'zgartiring.
HaroratsinfigaJudaIssiqhodisasini qo'shing.- Bitta hodisaga ikkita tinglovchi ulang.
RemoveHandlerbilan tinglovchini olib tashlang.
Xulosa #
Delegate- funksiyaning shakli;AddressOfaniq 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 Functionbilan 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+AddHandlersinflarni bir-biridan ajratadi.
Keyingi bo'limda generiklar va Nothing xavfsizligini ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.