14-bo‘lim

Xatoliklarni boshqarish

Try, Catch va Finally, xato turlari, Throw bilan xato ko'tarish, o'z xato sinfingiz, Using va nega On Error eskirgan.

🕑 12 daqiqa o‘qish 📄 624 so‘z 👁 0 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Try va Catch
  2. Bir necha Catch
  3. Xato haqida ma'lumot
  4. Finally
  5. Xatoni o'zingiz ko'tarish
  6. O'z xato sinfingiz
  7. Using - resursni o'zi yopadi
  8. Xatoni qayta ko'tarish
  9. On Error - eskirgan usul
  10. Qachon ushlash kerak
  11. Xulosa

Dastur ishlayotganda kutilmagan holatlar yuz beradi: fayl topilmaydi, foydalanuvchi harf yozadi, tarmoq uzilaadi. Bularni istisno (exception) deb ataymiz.

Try va Catch #

VB
Module Dastur
    Sub Main()
        Try
            Dim matn As String = "salom"
            Dim son As Integer = CInt(matn)
            Console.WriteLine(son)
        Catch ex As InvalidCastException
            Console.WriteLine("Bu matnni songa aylantirib bo'lmadi")
        End Try

        Console.WriteLine("Dastur davom etmoqda")
    End Sub
End Module
Natija
Bu matnni songa aylantirib bo'lmadi
Dastur davom etmoqda

Try blokidagi kod xato bersa, dastur to'xtamaydi - boshqaruv Catch ga o'tadi.

Bir necha Catch #

VB
Module Dastur
    Sub Sinov(bolovchi As Integer, sonlar() As Integer, indeks As Integer)
        Try
            Console.WriteLine(sonlar(indeks) \ bolovchi)
        Catch ex As DivideByZeroException
            Console.WriteLine("Nolga bo'lib bo'lmaydi")
        Catch ex As IndexOutOfRangeException
            Console.WriteLine("Bunday indeks yo'q")
        Catch ex As Exception
            Console.WriteLine($"Boshqa xato: {ex.GetType().Name}")
        End Try
    End Sub

    Sub Main()
        Dim sonlar() As Integer = {10, 20, 30}
        Sinov(2, sonlar, 0)
        Sinov(0, sonlar, 1)
        Sinov(2, sonlar, 99)
    End Sub
End Module
Natija
5
Nolga bo'lib bo'lmaydi
Bunday indeks yo'q
Tartib muhim - aniqrog'i oldin

Catch bloklari yuqoridan pastga tekshiriladi va birinchi mos kelgani ishlaydi.

Exception - hamma xatolarning otasi. Shuning uchun uni eng oxirida yozish kerak. Yuqoriga qo'ysangiz, qolganlari hech qachon ishlamaydi va kompilyator ogohlantirish beradi.

Xato haqida ma'lumot #

VB
Module Dastur
    Sub Main()
        Try
            Dim sonlar() As Integer = {1, 2, 3}
            Console.WriteLine(sonlar(10))
        Catch ex As Exception
            Console.WriteLine($"Turi: {ex.GetType().Name}")
            Dim bormi As Boolean = Not String.IsNullOrEmpty(ex.Message)
            Console.WriteLine($"Xabar bormi: {bormi}")
        End Try
    End Sub
End Module
Natija
Turi: IndexOutOfRangeException
Xabar bormi: True
Xato matnini bevosita chop etmadik

ex.Message matni .NET versiyasiga va tizim tiliga qarab o'zgarishi mumkin. Shuning uchun bu darslikda uning borligi tekshirildi, matnning o'zi emas.

Haqiqiy dasturda esa ex.Message ni jurnalga yozish juda foydali - muammoni topishning eng tez yo'li shu.

Finally #

VB
Module Dastur
    Function Bol(a As Integer, b As Integer) As String
        Try
            Return (a \ b).ToString()
        Catch ex As DivideByZeroException
            Return "xato"
        Finally
            Console.WriteLine("  Finally bajarildi")
        End Try
    End Function

    Sub Main()
        Console.WriteLine(Bol(10, 2))
        Console.WriteLine(Bol(10, 0))
    End Sub
End Module
Natija
  Finally bajarildi
5
  Finally bajarildi
xato

Finally har doim bajariladi: xato bo'lsa ham, bo'lmasa ham, hatto Return dan keyin ham. Fayl yoki ulanishni yopish uchun ishlatiladi.

Xatoni o'zingiz ko'tarish #

VB
Module Dastur
    Sub YoshTekshir(yosh As Integer)
        If yosh < 0 Then
            Throw New ArgumentException("Yosh manfiy bo'lishi mumkin emas")
        End If
        If yosh > 150 Then
            Throw New ArgumentOutOfRangeException("yosh")
        End If
        Console.WriteLine($"Yosh qabul qilindi: {yosh}")
    End Sub

    Sub Main()
        YoshTekshir(25)

        Try
            YoshTekshir(-5)
        Catch ex As ArgumentException
            Console.WriteLine($"Ushlandi: {ex.GetType().Name}")
        End Try
    End Sub
End Module
Natija
Yosh qabul qilindi: 25
Ushlandi: ArgumentException

Throw - "bu holatni men bajara olmayman, chaqiruvchi hal qilsin" degan xabar.

O'z xato sinfingiz #

VB
Public Class QoldiqYetarliEmasException
    Inherits Exception

    Public Property Yetishmayotgan As Decimal

    Public Sub New(yetishmayotgan As Decimal)
        MyBase.New($"Hisobda {yetishmayotgan} so'm yetishmayapti")
        Me.Yetishmayotgan = yetishmayotgan
    End Sub
End Class

Public Class Hisob
    Private _qoldiq As Decimal

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

    Public Sub Yechish(summa As Decimal)
        If summa > _qoldiq Then
            Throw New QoldiqYetarliEmasException(summa - _qoldiq)
        End If
        _qoldiq -= summa
        Console.WriteLine($"Yechildi. Qoldiq: {_qoldiq}")
    End Sub
End Class

Module Dastur
    Sub Main()
        Dim h As New Hisob(500000D)

        Try
            h.Yechish(200000D)
            h.Yechish(900000D)
        Catch ex As QoldiqYetarliEmasException
            Console.WriteLine(ex.Message)
            Console.WriteLine($"Yetishmayotgan summa: {ex.Yetishmayotgan}")
        End Try
    End Sub
End Module
Natija
Yechildi. Qoldiq: 300000
Hisobda 600000 so'm yetishmayapti
Yetishmayotgan summa: 600000

ex.Message - konstruktorda MyBase.New ga berilgan matn. Asosiy foydasi esa Yetishmayotgan xossasi: oddiy Exception faqat matn tashiydi, o'z sinfingiz esa ishlov berish uchun yaroqli ma'lumot ham tashiy oladi.

Matnni tahlil qilib son ajratib olishga urinish - noto'g'ri yo'l. Kerakli qiymatni xossa sifatida qo'shing.

Using - resursni o'zi yopadi #

VB
Imports System.IO

Module Dastur
    Sub Main()
        Dim yol As String = "sinov.txt"

        Using yozuvchi As New StreamWriter(yol)
            yozuvchi.WriteLine("Birinchi qator")
            yozuvchi.WriteLine("Ikkinchi qator")
        End Using

        Console.WriteLine(File.ReadAllText(yol).Trim())
        File.Delete(yol)
    End Sub
End Module
Natija
Birinchi qator
Ikkinchi qator

Using bloki tugaganda - xato bo'lsa ham - resurs avtomatik yopiladi. Bu Try/Finally ning qisqa shakli.

Fayl va ulanish uchun har doim Using

Using yozmasangiz va xato yuz bersa, fayl ochiq qolishi mumkin. Keyin uni boshqa dastur o'chira ham, o'zgartira ham olmaydi.

Qoida oddiy: StreamReader, StreamWriter, ma'lumotlar bazasi ulanishi - bularning hammasi Using ichida bo'lishi kerak.

Xatoni qayta ko'tarish #

VB
Module Dastur
    Sub Ichki()
        Throw New InvalidOperationException("ichki xato")
    End Sub

    Sub Ortadagi()
        Try
            Ichki()
        Catch ex As Exception
            Console.WriteLine("Jurnalga yozildi")
            Throw
        End Try
    End Sub

    Sub Main()
        Try
            Ortadagi()
        Catch ex As Exception
            Console.WriteLine($"Yuqorida ushlandi: {ex.Message}")
        End Try
    End Sub
End Module
Natija
Jurnalga yozildi
Yuqorida ushlandi: ichki xato

Yolg'iz Throw - "xatoni o'zgartirmasdan yuqoriga uzat" degani. Throw ex deb yozsangiz, xatoning kelib chiqish joyi yo'qoladi.

On Error - eskirgan usul #

VB
' VB6 uslubi - yangi kodda ishlatmang
On Error Resume Next
Dim son As Integer = CInt("salom")
On Error Goto 0
On Error Resume Next - eng xavfli qator

Bu ko'rsatma "xato bo'lsa, e'tiborsiz qoldir va davom et" degani.

Natijada dastur noto'g'ri ma'lumot bilan ishlashda davom etadi va haqiqiy muammo ancha keyin, butunlay boshqa joyda ko'rinadi. Sababini topish esa deyarli imkonsiz bo'lib qoladi.

VB.NET da u hali ham ishlaydi (eski kod uchun), lekin yangi kodda hech qachon ishlatmang. Try/Catch bor.

Qachon ushlash kerak #

HolatTo'g'ri yo'l
Foydalanuvchi noto'g'ri son yozdiTryParse - istisno umuman kerak emas
Fayl yo'qligi mumkinFile.Exists tekshiruvi yoki Catch
Tarmoq uzilishiCatch - oldindan bilib bo'lmaydi
Dasturchining xatosiUshlamang - kod tuzatilishi kerak
Bo'sh Catch yozmang

Bu eng yomon namuna:

VB
Try
    ' biror ish
Catch ex As Exception
    ' hech narsa
End Try

Xato yuz berdi, lekin hech kim bilmaydi. Dastur "ishlayotgandek" ko'rinadi, aslida esa ish bajarilmadi.

Hech bo'lmaganda xabarni jurnalga yozing yoki ekranga chiqaring.

Amaliy topshiriq
  1. Nolga bo'lishni Try/Catch bilan ushlang.
  2. Massivdan chiqib ketishni alohida Catch bilan ushlang.
  3. Exception ni birinchi Catch ga qo'yib, ogohlantirishni o'qing.
  4. Finally blokining har doim bajarilishini isbotlang.
  5. Manfiy yoshda ArgumentException ko'taring.
  6. MaxsulotTopilmadiException nomli o'z xato sinfingizni yozing.
  7. Unga qo'shimcha xossa qo'shib, Catch da o'qing.
  8. Using bilan faylga yozing va uni o'chiring.
  9. Xatoni ushlab, jurnalga yozib, Throw bilan qayta ko'taring.
  10. TryParse va Try/Catch dan qaysi biri qachon to'g'ri kelishini yozing.

Xulosa #

  • Try/Catch xato yuz berganda dasturning to'xtashiga yo'l qo'ymaydi.
  • Catch bloklari aniqrog'idan umumiyga qarab yoziladi; Exception eng oxirida.
  • Finally har doim bajariladi - resursni yopish uchun.
  • Throw New ... bilan o'z xatongizni ko'tarasiz.
  • O'z xato sinfingiz Exception dan meros oladi va qo'shimcha ma'lumot tashiy oladi.
  • Using - fayl va ulanishlar uchun majburiy odat.
  • Yolg'iz Throw xatoning kelib chiqishini saqlaydi, Throw ex esa yo'qotadi.
  • On Error Resume Next - eski va xavfli; ishlatmang.
  • Kutilgan holat uchun TryParse, kutilmagan uchun Try/Catch.

Keyingi bo'limda fayllar va JSON bilan ishlaymiz.

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.