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.
Ushbu bo‘lim mundarijasi
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 #
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");
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 #
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");
}
}
'42' -> 42
'abc' -> raqam emas
'' -> raqam emas
Diqqat: bo'sh satr ham FormatException berdi, ArgumentNullException
emas - chunki u null emas, shunchaki bo'sh.
Istisnolar kutilmagan holatlar uchun. Foydalanuvchi noto'g'ri ma'lumot kiritishi esa kutilgan holat.
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");
}
}
'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 #
try
{
int[] sonlar = [1, 2, 3];
Console.WriteLine(sonlar[10]);
}
catch (IndexOutOfRangeException x)
{
Console.WriteLine($"Turi: {x.GetType().Name}");
Console.WriteLine($"Xabar: {x.Message}");
}
Turi: IndexOutOfRangeException
Xabar: Index was outside the bounds of the array.
| Xossa | Nima beradi |
|---|---|
Message | Odam o'qiy oladigan izoh |
StackTrace | Qaysi qatorlardan o'tgani |
InnerException | Asl sabab (o'ralgan bo'lsa) |
GetType().Name | Istisno turi |
finally #
finally bloki har doim bajariladi - istisno bo'ldimi yoki yo'qmi:
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");
}
}
[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:
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");
}
baza ishlatilmoqda
baza yopildi
---
fayl ishlatilmoqda
fayl yopildi
using aslida try/finally ning qisqa yozuvi: istisno bo'lsa ham
Dispose() chaqiriladi.
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 #
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;
}
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 #
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;
}
404: sahifa topilmadi
500: server xatosi
when sharti bajarilmasa, catch bloki umuman ishga tushmaydi va
istisno keyingi bloklarga uzatiladi.
Standart istisno turlari #
| Tur | Qachon |
|---|---|
ArgumentException | Argument noto'g'ri |
ArgumentNullException | Argument null |
ArgumentOutOfRangeException | Argument diapazondan tashqarida |
InvalidOperationException | Obyekt hozir bunga tayyor emas |
FormatException | Satr formati noto'g'ri |
NotSupportedException | Bu amal qo'llab-quvvatlanmaydi |
IOException | Fayl yoki tarmoq muammosi |
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");
}
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 #
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 ushlamangtry { /* ... */ }
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 farqicatch (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 #
| Holat | Qaror |
|---|---|
| Foydalanuvchi noto'g'ri yozdi | Tekshiring, istisno tashlamang |
| Metod argumenti noto'g'ri | Istisno - bu dasturchi xatosi |
| Fayl topilmadi | Holatga bog'liq: ikkalasi ham to'g'ri |
| Tarmoq uzildi | Istisno - kutilmagan holat |
| Ro'yxat bo'sh | Odatda istisno emas |
- Nolga bo'lishni
try/catchbilan ushlang. int.Parseni noto'g'ri satr bilan chaqirib, istisnoni ushlang.- Xuddi shuni
TryParsebilan qayta yozing va solishtiring. finallyblokining har doim bajarilishini tekshiring.IDisposableamalga oshirgan sinf yozing vausingbilan ishlating.- O'z istisno turingizni yarating va qo'shimcha ma'lumot qo'shing.
whenfiltri bilan ikki xil holatni ajrating.ArgumentException.ThrowIfNullOrWhiteSpaceni sinang.- Bo'sh
catchnega yomon ekanini yozing. throw xvathrowfarqini o'z so'zingiz bilan tushuntiring.
Xulosa #
try/catchistisnoni ushlaydi,finallyhar doim bajariladi.- Oldindan tekshirish mumkin bo'lsa - istisno emas, tekshiruv
(
TryParse). usingIDisposableresurslarini har qanday holatda yopadi.- O'z istisno turingiz aniq ma'lumot tashiydi.
whenfiltri 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.
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.