18-bo‘lim
Generiklar va Nothing xavfsizligi
Of T bilan universal sinf va funksiya yozish, cheklovlar, Nullable qiymat turlari va NullReferenceException dan qochish.
Ushbu bo‘lim mundarijasi
Generik - tur nomini keyinroq aytishga imkon beradigan yozuv.
List(Of String) va List(Of Integer) - bitta sinfning ikki
ko'rinishi.
Generik funksiya #
Module Dastur
Function Almashtir(Of T)(ByRef a As T, ByRef b As T)
Dim vaqtinchalik As T = a
a = b
b = vaqtinchalik
End Function
Sub Main()
Dim x As Integer = 10, y As Integer = 20
Almashtir(x, y)
Console.WriteLine($"{x}, {y}")
Dim m As String = "birinchi", n As String = "ikkinchi"
Almashtir(m, n)
Console.WriteLine($"{m}, {n}")
End Sub
End Module
20, 10
ikkinchi, birinchi
Bitta funksiya - ikkala tur uchun. T - shunchaki nom, uning
o'rniga har qanday tur kelishi mumkin.
Object ham har qanday turni saqlaydi. Lekin unda ikki muammo bor:
- Qiymatni qaytarib olish uchun har safar aylantirish kerak va xato turni yozsangiz, xato dastur ishlayotganda chiqadi.
- Qiymat turlari (
Integerkabi) "quti"ga solinadi va bu sekin.
Generik esa turni kompilyatsiya paytida biladi: xato oldin topiladi va qo'shimcha ish bajarilmaydi.
Generik sinf #
Public Class Quti(Of T)
Private _elementlar As New List(Of T)
Public Sub Solish(element As T)
_elementlar.Add(element)
End Sub
Public Function Olish(indeks As Integer) As T
Return _elementlar(indeks)
End Function
Public ReadOnly Property Soni As Integer
Get
Return _elementlar.Count
End Get
End Property
End Class
Module Dastur
Sub Main()
Dim sonlar As New Quti(Of Integer)
sonlar.Solish(10)
sonlar.Solish(20)
Console.WriteLine($"{sonlar.Soni} ta, birinchisi {sonlar.Olish(0)}")
Dim ismlar As New Quti(Of String)
ismlar.Solish("Malika")
Console.WriteLine($"{ismlar.Soni} ta, birinchisi {ismlar.Olish(0)}")
End Sub
End Module
2 ta, birinchisi 10
1 ta, birinchisi Malika
Cheklovlar #
Ba'zan T dan biror narsani talab qilish kerak:
Module Dastur
Function Kattasi(Of T As IComparable(Of T))(a As T, b As T) As T
If a.CompareTo(b) >= 0 Then
Return a
End If
Return b
End Function
Sub Main()
Console.WriteLine(Kattasi(15, 42))
Console.WriteLine(Kattasi("olma", "anor"))
Console.WriteLine(Kattasi(3.7, 2.1))
End Sub
End Module
42
olma
3.7
As IComparable(Of T) - "T solishtirila oladigan tur bo'lishi
shart" degani. Usiz CompareTo ni chaqirib bo'lmasdi.
| Cheklov | Ma'nosi |
|---|---|
As Class | Havola turi bo'lishi shart |
As Structure | Qiymat turi bo'lishi shart |
As New | Parametrsiz konstruktori bo'lishi shart |
As IBiror | Shu interfeysni bajarishi shart |
As {Class, New} | Bir nechta shart |
Public Class Omborxona(Of T As {Class, New})
Public Function Yangi() As T
Return New T()
End Function
End Class
Public Class Hujjat
Public Property Nom As String = "yangi hujjat"
End Class
Module Dastur
Sub Main()
Dim o As New Omborxona(Of Hujjat)
Dim h As Hujjat = o.Yangi()
Console.WriteLine(h.Nom)
End Sub
End Module
yangi hujjat
As New cheklovi bo'lmasa, New T() yozib bo'lmaydi - kompilyator
T da konstruktor borligini bilmaydi.
Nothing muammosi #
Module Dastur
Function Topish(royxat As List(Of String), qidiruv As String) As String
For Each s As String In royxat
If s = qidiruv Then
Return s
End If
Next
Return Nothing
End Function
Sub Main()
Dim royxat As New List(Of String) From {"olma", "anor"}
Dim topildi As String = Topish(royxat, "uzum")
Console.WriteLine(topildi Is Nothing)
If topildi IsNot Nothing Then
Console.WriteLine(topildi.ToUpper())
Else
Console.WriteLine("Topilmadi")
End If
End Sub
End Module
True
Topilmadi
Agar yuqoridagi tekshiruvsiz topildi.ToUpper() deb yozsangiz,
dastur NullReferenceException bilan to'xtaydi.
Bu dunyodagi eng ko'p uchraydigan dastur xatosi. Undan qochishning uch yo'li:
- Har doim
IsNot Nothingbilan tekshirish. Nothingqaytarmaslik - bo'sh ro'yxat yoki bo'sh satr qaytarish.If(qiymat, zaxira)bilan zaxira qiymat berish.
Nullable qiymat turlari #
Integer hech qachon bo'sh bo'lolmaydi - uning standart qiymati 0.
Lekin "qiymat kiritilmagan" holatini ko'rsatish kerak bo'lsa-chi?
Module Dastur
Sub Main()
Dim ball As Integer? = Nothing
Console.WriteLine(ball.HasValue)
Console.WriteLine(ball.GetValueOrDefault())
Console.WriteLine(ball.GetValueOrDefault(-1))
ball = 88
Console.WriteLine(ball.HasValue)
Console.WriteLine(ball.Value)
End Sub
End Module
False
0
-1
True
88
Integer? - bu Nullable(Of Integer) ning qisqa yozuvi.
| A'zo | Nima qiladi |
|---|---|
HasValue | Qiymat bormi |
Value | Qiymatni oladi (bo'lmasa xato) |
GetValueOrDefault() | Bo'lmasa turning standart qiymati |
GetValueOrDefault(x) | Bo'lmasa x |
0 va "qiymat yo'q" farqi #
Module Dastur
Sub Korsat(nom As String, ball As Integer?)
If ball.HasValue Then
Console.WriteLine($"{nom}: {ball.Value} ball")
Else
Console.WriteLine($"{nom}: imtihon topshirmagan")
End If
End Sub
Sub Main()
Korsat("Malika", 88)
Korsat("Husanboy", 0)
Korsat("Nodira", Nothing)
End Sub
End Module
Malika: 88 ball
Husanboy: 0 ball
Nodira: imtihon topshirmagan
Mana nima uchun Integer? kerak: 0 ball olgan talaba bilan
imtihonga kelmagan talaba - butunlay boshqa holatlar. Oddiy
Integer bilan ularni ajratib bo'lmaydi.
Zaxira qiymat #
Module Dastur
Sub Main()
Dim kiritilgan As String = Nothing
Console.WriteLine(If(kiritilgan, "noma'lum"))
Dim ball As Integer? = Nothing
Console.WriteLine(If(ball, 0))
Dim royxat As List(Of String) = Nothing
Dim xavfsiz = If(royxat, New List(Of String))
Console.WriteLine(xavfsiz.Count)
End Sub
End Module
noma'lum
0
0
If(a, b) - "a bor bo'lsa a, yo'q bo'lsa b". Eng qisqa va eng
xavfsiz shakl.
Funksiya ro'yxat qaytarishi kerak bo'lsa, hech narsa topilmaganda
Nothing emas, bo'sh ro'yxat qaytaring.
Shunda chaqiruvchi tekshirmasdan For Each qila oladi - bo'sh
ro'yxat bo'ylab yurish xato bermaydi, shunchaki hech narsa
bajarilmaydi.
Bu kichik odat NullReferenceException larning yarmini yo'q qiladi.
Generik va Nullable birga #
Module Dastur
Function XavfsizOrtacha(sonlar As List(Of Integer)) As Double?
If sonlar Is Nothing OrElse sonlar.Count = 0 Then
Return Nothing
End If
Return sonlar.Average()
End Function
Sub Main()
Dim toliq As New List(Of Integer) From {80, 90, 100}
Dim bosh As New List(Of Integer)
Dim a As Double? = XavfsizOrtacha(toliq)
Dim b As Double? = XavfsizOrtacha(bosh)
Console.WriteLine(If(a.HasValue, a.Value.ToString(),
"hisoblab bo'lmadi"))
Console.WriteLine(If(b.HasValue, b.Value.ToString(),
"hisoblab bo'lmadi"))
End Sub
End Module
90
hisoblab bo'lmadi
Bo'sh ro'yxatning o'rtachasi mavjud emas - 0 ham noto'g'ri javob
bo'lardi. Double? aynan shuni ifodalaydi.
- Ikkita qiymatni almashtiruvchi generik funksiya yozing.
Quti(Of T)sinfiniDoublebilan sinang.- Ro'yxatdagi eng kattasini topadigan generik funksiya yozing.
As Newcheklovi bilan obyekt yasovchi sinf yarating.- Cheklovni olib tashlab, xatoni o'qing.
Nothingqaytaradigan funksiya yozib, uni xavfsiz chaqiring.Integer?bilan "kiritilmagan" holatini ifodalang.GetValueOrDefault(-1)ni sinab ko'ring.If(qiymat, zaxira)bilan bo'sh ro'yxatni almashtiring.- Bo'sh ro'yxatning o'rtachasini
Double?bilan qaytaring.
Xulosa #
Of T- turni keyinroq aytish imkoni;Objectdan tez va xavfsizroq.- Cheklovlar (
As Class,As New,As IComparable(Of T))Tdan nimani talab qilishni belgilaydi. NullReferenceException- eng ko'p uchraydigan xato; har doimIsNot Nothingbilan tekshiring.Integer?-Nullable(Of Integer):0bilan "qiymat yo'q" ni ajratadi.HasValue,Value,GetValueOrDefault(x)- asosiy a'zolar.If(a, b)- zaxira qiymat berishning eng qisqa yo'li.- Funksiyadan
Nothingemas, bo'sh ro'yxat qaytaring.
Keyingi bo'limda asinxron dasturlashni 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.