13-bo‘lim

Istisnolar

try, catch va finally, istisno turlari, o'z istisnongizni yaratish, when filtri, using va IDisposable hamda istisnolarni to'g'ri ishlatish qoidalari.

🕑 13 daqiqa o‘qish 📄 647 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. try va catch
  2. Bir nechta catch
  3. Istisno haqida ma'lumot olish
  4. finally
  5. using - avtomatik tozalash
  6. O'z istisnongiz
  7. when filtri
  8. Standart istisno turlari
  9. Nima qilmaslik kerak
  10. Qachon istisno tashlash kerak
  11. Xulosa

Istisno - dastur davom eta olmaydigan holat: fayl topilmadi, tarmoq uzildi, foydalanuvchi noto'g'ri ma'lumot berdi.

C# da bunday holatlar istisno (exception) orqali xabar qilinadi.

try va catch #

CSHARP
try
{
    int a = 10;
    int b = 0;
    Console.WriteLine(a / b);
}
catch (DivideByZeroException)
{
    Console.WriteLine("Nolga bo'lib bo'lmaydi");
}

Console.WriteLine("Dastur davom etmoqda");
Natija
Nolga bo'lib bo'lmaydi
Dastur davom etmoqda

catch bo'lmaganida dastur to'xtardi. U bilan esa xatoni ushlab, ishni davom ettirdik.

Bir nechta catch #

CSHARP
string[] kirishlar = ["42", "abc", ""];

foreach (string kirish in kirishlar)
{
    try
    {
        int son = int.Parse(kirish);
        Console.WriteLine($"'{kirish}' -> {son}");
    }
    catch (FormatException)
    {
        Console.WriteLine($"'{kirish}' -> raqam emas");
    }
    catch (ArgumentNullException)
    {
        Console.WriteLine($"'{kirish}' -> bo'sh qiymat");
    }
}
Natija
'42' -> 42
'abc' -> raqam emas
'' -> raqam emas

Diqqat: bo'sh satr ham FormatException berdi, ArgumentNullException emas - chunki u null emas, shunchaki bo'sh.

Istisnodan oldin tekshiruvni afzal ko'ring

Istisnolar kutilmagan holatlar uchun. Foydalanuvchi noto'g'ri ma'lumot kiritishi esa kutilgan holat.

CSHARP
string[] kirishlar = ["42", "abc"];

foreach (string kirish in kirishlar)
{
    if (int.TryParse(kirish, out int son))
    {
        Console.WriteLine($"'{kirish}' -> {son}");
    }
    else
    {
        Console.WriteLine($"'{kirish}' -> raqam emas");
    }
}
Natija
'42' -> 42
'abc' -> raqam emas

Bu nafaqat toza ko'rinadi, balki tezroq ham ishlaydi: istisno tashlash va ushlash qimmat amal - stek holati saqlanadi, obyekt yaratiladi.

Qoida: oldindan tekshirish mumkin bo'lsa - tekshiring.

Istisno haqida ma'lumot olish #

CSHARP
try
{
    int[] sonlar = [1, 2, 3];
    Console.WriteLine(sonlar[10]);
}
catch (IndexOutOfRangeException x)
{
    Console.WriteLine($"Turi:    {x.GetType().Name}");
    Console.WriteLine($"Xabar:   {x.Message}");
}
Natija
Turi:    IndexOutOfRangeException
Xabar:   Index was outside the bounds of the array.
XossaNima beradi
MessageOdam o'qiy oladigan izoh
StackTraceQaysi qatorlardan o'tgani
InnerExceptionAsl sabab (o'ralgan bo'lsa)
GetType().NameIstisno turi

finally #

finally bloki har doim bajariladi - istisno bo'ldimi yoki yo'qmi:

CSHARP
foreach (string holat in new[] { "yaxshi", "yomon" })
{
    try
    {
        Console.WriteLine($"[{holat}] boshlandi");
        if (holat == "yomon")
        {
            throw new InvalidOperationException("xato yuz berdi");
        }
        Console.WriteLine($"[{holat}] muvaffaqiyatli");
    }
    catch (InvalidOperationException x)
    {
        Console.WriteLine($"[{holat}] ushlandi: {x.Message}");
    }
    finally
    {
        Console.WriteLine($"[{holat}] tozalash bajarildi");
    }
}
Natija
[yaxshi] boshlandi
[yaxshi] muvaffaqiyatli
[yaxshi] tozalash bajarildi
[yomon] boshlandi
[yomon] ushlandi: xato yuz berdi
[yomon] tozalash bajarildi

using - avtomatik tozalash #

Fayl, tarmoq ulanishi va shunga o'xshash resurslar ishlatilgandan keyin yopilishi kerak. using buni avtomatik qiladi:

CSHARP
using (var manba = new Manba("baza"))
{
    manba.Ishlat();
}

Console.WriteLine("---");

// qisqa yozuv: blok tugaganda yopiladi
using var ikkinchi = new Manba("fayl");
ikkinchi.Ishlat();

class Manba(string nom) : IDisposable
{
    public void Ishlat() => Console.WriteLine($"{nom} ishlatilmoqda");
    public void Dispose() => Console.WriteLine($"{nom} yopildi");
}
Natija
baza ishlatilmoqda
baza yopildi
---
fayl ishlatilmoqda
fayl yopildi

using aslida try/finally ning qisqa yozuvi: istisno bo'lsa ham Dispose() chaqiriladi.

Faylni qo'lda yopmang
CSHARP
var oqim = File.OpenText("fayl.txt");
// ... agar shu yerda istisno bo'lsa ...
oqim.Close();                             // BU CHAQIRILMAYDI

using bilan esa fayl har qanday holatda yopiladi. IDisposable amalga oshirgan har bir turni har doim using bilan ishlating.

O'z istisnongiz #

CSHARP
try
{
    Yechish(-5);
}
catch (SalbiyQiymatException x)
{
    Console.WriteLine($"Ushlandi: {x.Message}");
    Console.WriteLine($"Xato qiymat: {x.Qiymat}");
}

void Yechish(int son)
{
    if (son < 0)
    {
        throw new SalbiyQiymatException(son);
    }

    Console.WriteLine(Math.Sqrt(son));
}

class SalbiyQiymatException(int qiymat)
    : Exception($"Manfiy qiymat qabul qilinmaydi: {qiymat}")
{
    public int Qiymat => qiymat;
}
Natija
Ushlandi: Manfiy qiymat qabul qilinmaydi: -5
Xato qiymat: -5

O'z istisno turingiz chaqiruvchiga aniq nima bo'lganini bildiradi va qo'shimcha ma'lumot tashiy oladi.

when filtri #

CSHARP
foreach (int kod in new[] { 404, 500 })
{
    try
    {
        throw new HttpException(kod);
    }
    catch (HttpException x) when (x.Kod == 404)
    {
        Console.WriteLine($"{x.Kod}: sahifa topilmadi");
    }
    catch (HttpException x)
    {
        Console.WriteLine($"{x.Kod}: server xatosi");
    }
}

class HttpException(int kod) : Exception($"HTTP {kod}")
{
    public int Kod => kod;
}
Natija
404: sahifa topilmadi
500: server xatosi

when sharti bajarilmasa, catch bloki umuman ishga tushmaydi va istisno keyingi bloklarga uzatiladi.

Standart istisno turlari #

TurQachon
ArgumentExceptionArgument noto'g'ri
ArgumentNullExceptionArgument null
ArgumentOutOfRangeExceptionArgument diapazondan tashqarida
InvalidOperationExceptionObyekt hozir bunga tayyor emas
FormatExceptionSatr formati noto'g'ri
NotSupportedExceptionBu amal qo'llab-quvvatlanmaydi
IOExceptionFayl yoki tarmoq muammosi
CSHARP
try
{
    Royxatga("");
}
catch (ArgumentException x)
{
    Console.WriteLine($"{x.GetType().Name}: {x.Message}");
}

void Royxatga(string ism)
{
    ArgumentException.ThrowIfNullOrWhiteSpace(ism);
    Console.WriteLine($"{ism} ro'yxatga olindi");
}
Natija
ArgumentException: The value cannot be an empty string or composed entirely of whitespace. (Parameter 'ism')

ThrowIfNullOrWhiteSpace kabi yordamchi metodlar zamonaviy .NET da tekshiruvni bir qatorga qisqartiradi.

Nima qilmaslik kerak #

Bo'sh catch - eng yomon amaliyot
CSHARP
try
{
    // biror ish
}
catch
{
    // hech narsa
}

Bu xatoni yashiradi: dastur noto'g'ri ishlaydi, lekin siz bilmaysiz. Nosozlikni topish deyarli imkonsiz bo'lib qoladi.

Agar istisnoni haqiqatan e'tiborsiz qoldirish kerak bo'lsa, nega shunday qilinayotganini izohda yozing.

catch (Exception) bilan hammasini ushlamang
CSHARP
try { /* ... */ }
catch (Exception) { Console.WriteLine("nimadir xato"); }

Bu OutOfMemoryException va dasturchi xatosi bo'lgan NullReferenceException ni ham ushlaydi - ya'ni tuzatilishi kerak bo'lgan xatolarni yashiradi.

Faqat qanday ishlashni bilgan istisnolaringizni ushlang. Qolgani yuqoriga ko'tarilib, jurnal yozuvida ko'rinsin.

throw va throw x farqi
CSHARP
catch (Exception x)
{
    throw x;        // YOMON - stek izi yo'qoladi
}

catch (Exception)
{
    throw;          // YAXSHI - asl stek izi saqlanadi
}

throw x istisnoni qaytadan tashlaydi va u qayerdan boshlangani haqidagi ma'lumot yo'qoladi. Natijada jurnalda xato sizning catch blokingizdan boshlangandek ko'rinadi.

Shunchaki throw; yozing.

Qachon istisno tashlash kerak #

HolatQaror
Foydalanuvchi noto'g'ri yozdiTekshiring, istisno tashlamang
Metod argumenti noto'g'riIstisno - bu dasturchi xatosi
Fayl topilmadiHolatga bog'liq: ikkalasi ham to'g'ri
Tarmoq uzildiIstisno - kutilmagan holat
Ro'yxat bo'shOdatda istisno emas
Amaliy topshiriq
  1. Nolga bo'lishni try/catch bilan ushlang.
  2. int.Parse ni noto'g'ri satr bilan chaqirib, istisnoni ushlang.
  3. Xuddi shuni TryParse bilan qayta yozing va solishtiring.
  4. finally blokining har doim bajarilishini tekshiring.
  5. IDisposable amalga oshirgan sinf yozing va using bilan ishlating.
  6. O'z istisno turingizni yarating va qo'shimcha ma'lumot qo'shing.
  7. when filtri bilan ikki xil holatni ajrating.
  8. ArgumentException.ThrowIfNullOrWhiteSpace ni sinang.
  9. Bo'sh catch nega yomon ekanini yozing.
  10. throw x va throw farqini o'z so'zingiz bilan tushuntiring.

Xulosa #

  • try/catch istisnoni ushlaydi, finally har doim bajariladi.
  • Oldindan tekshirish mumkin bo'lsa - istisno emas, tekshiruv (TryParse).
  • using IDisposable resurslarini har qanday holatda yopadi.
  • O'z istisno turingiz aniq ma'lumot tashiydi.
  • when filtri bitta tur ichida holatlarni ajratadi.
  • Bo'sh catch - xatoni yashiradi, hech qachon yozmang.
  • catch (Exception) bilan hammasini ushlamang.
  • Qayta tashlaganda throw; yozing, throw x; emas - stek izi saqlanadi.

Keyingi bo'limda generiklarni o'rganamiz.

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.