CodeGym /Kurslar /C# SELF /Çoxlu catch və filterlər C#-da

Çoxlu catch və filterlər C#-da

C# SELF
Səviyyə, Dərs
Mövcuddur

1. Giriş

Proqram bir az Hello, world!-dan mürəkkəb olanda, tezliklə belə bir problemlə rastlaşırsan: müxtəlif error-ları fərqli cür idarə etmək lazımdır. Təsəvvür elə: sən fayllarla, şəbəkə ilə, DB ilə işləyirsən — və hər error ssenarisi üçün fərqli reaksiya lazımdır. Məsələn, fayl yoxdursa, istifadəçiyə başqa fayl seçməyi təklif edə bilərsən, şəbəkə error-u varsa — əməliyyatı təkrarlamağı və ya "Kabeli yoxla, bəlkə pişik yenə dişləyib" kimi motivasiyaedici mesaj göstərmək olar.

C#-da bunun üçün ardıcıl bir neçə catch bloku istifadə olunur. Hər blok öz exception tipinə (və onun törəmələrinə) fokuslanır.

Çoxlu catch strukturu


try
{
    // Burada — müxtəlif exception-lar ata biləcək kod
}
catch (FileNotFoundException ex)
{
    Console.WriteLine($"Fayl tapılmadı: {ex.Message}");
}
catch (IOException ex) // FileNotFoundException deyil, bütün input/output error-ları tutur
{
    Console.WriteLine($"Input-output xətası: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"Nəsə düz getmədi: {ex.Message}");
}
Müxtəlif error tipləri üçün çoxlu catch blokları

Vacibdir! Kompilyator bloklardan yuxarıdan aşağıya keçir və ilk uyğun olanı seçir. Əgər FileNotFoundException tutulubsa, artıq aşağıdakı bloklara keçmir.

"Zəncir" illüstrasiyası

Exception tipi Hansı blok tutacaq?
FileNotFoundException Birinci catch
IOException (başqa) İkinci catch
ArgumentException Üçüncü (ümumi) catch

Niyə qarışdırmaq olmaz?
Ən "geniş" tələni — məsələn, catch (Exception) — həmişə axırda qoy, yoxsa o, bütün exception-ları vaxtından əvvəl "udacaq" və xüsusi catch-lara çatmayacaq.

Bu, binadakı bütün yanğın detektorlarını söndürməyə bənzəyir, çünki biri tost yananda işə düşüb: belə olsa, sonrakı yanğınları sistem görməyəcək.

İşlək nümunə

using System;
using System.IO;

class Program
{
    static void Main()
    {
        try
        {
            double result = CalculateAverageAgeFromFile("users.txt");
            Console.WriteLine($"Orta yaş — {result}");
        }
        catch (FileNotFoundException ex)
        {
            Console.WriteLine("Xəta: fayl tapılmadı. Yolu yoxlayın.");
        }
        catch (FormatException ex)
        {
            Console.WriteLine("Data xətası: yaşı oxumaq olmur.");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Başqa xəta: {ex.Message}");
        }
    }

    static double CalculateAverageAgeFromFile(string filePath)
    {
        // (Reallaşdırma: faylı oxuyur, yaşları parse edir, orta hesablayır)
        // ...
        throw new NotImplementedException();
    }
}

Burada biz açıq şəkildə ayırırıq ki, fayl yoxdursa (FileNotFoundException), nə etmək lazımdır, və əgər faylda "əyri" data varsa (FormatException) nə etmək lazımdır. Qalan halları "ehtiyat" üçüncü blok tutur.

2. catch filterləri: incə nüansları tuturuq

Çoxlu catch blokları rahatdır, amma bəzən bu kifayət etmir. Elə hallar olur ki, bir exception tipinin içində də fərqli reaksiya vermək istəyirsən, şəraitdən asılı olaraq.

Məsələn, əgər şəbəkə işləmir, çünki internet bitib — yenidən qoşulmağa cəhd edə bilərik. Amma server cavab vermirsə — bəlkə başqa mesaj göstərmək lazımdır.

Bax, burada catch filterləri — C#-ın əsl super-funksiyası — köməyə gəlir, çünki onlar exception-u təkcə tipinə görə yox, əlavə şərtə görə də tuta bilir.

when filterinin sintaksisi


catch (IOException ex) when (ex.Message.Contains("disk yoxdur"))
{
    Console.WriteLine("Ups! Görünür, flashı çıxartmısınız.");
}
catch (IOException ex)
{
    Console.WriteLine("Başqa input/output xətası: " + ex.Message);
}
Tutma şərtlərini dəqiqləşdirmək üçün catch when filteri

Burada birinci blok yalnız o IOException-ları tutur ki, mesajında "disk yoxdur" frazası var — qalanları ikinci bloka keçir.

Real həyatda tətbiqi

Filterlər xüsusilə şəbəkə error-ları ilə işləyərkən faydalıdır, çünki exception-un daxili xüsusiyyətlərinə görə qərar vermək olur: cəhd təkrarlansın, yoxsa sadəcə error göstərilsin.

Başqa bir nümunə: təsəvvür elə, faylı parse edən metodda biz təkcə "qəzəbli" FormatException yox, xüsusi halda — əgər söhbət yaşdan gedirsə (məsələn, yaş "abc" kimi yazılıbsa) ayrıca reaksiya vermək istəyirik.

catch (FormatException ex) when (ex.Message.Contains("yaş"))
{
    Console.WriteLine("Xəta: yaşı oxumaq mümkün olmadı. Dataya baxın.");
}
catch (FormatException ex)
{
    Console.WriteLine("Data formatı xətası: " + ex.Message);
}

Filterlər və performans

Filterlər — rahat şeydir, amma yadında saxla ki, filterdəki şərt catch blokuna girməmişdən əvvəl hesablanır, yəni əgər şərt ödənmirsə — blokun içi heç işə düşmür.

Bu arada, əgər filterin içində exception atılsa (məsələn, when ifadəndə sıfıra bölmə baş verərsə) — bu exception həmin catch bloku tərəfindən heç vaxt tutulmayacaq. Bununla ehtiyatlı ol.

3. Çoxlu catch və filterləri birləşdiririk

Təsəvvür elə ki, layihəndə təkcə exception tipini yox, onun daxili vəziyyətini də idarə etmək lazımdır. Məsələn, IOException ilə işləyərkən, error fayl sistemində icazə ilə bağlıdırsa və ya diskdə yer yoxdursa, fərqli davranmaq istəyirik.


try
{
    File.AppendAllText("log.txt", "Yeni qeyd\n");
}
catch (IOException ex) when (ex.Message.Contains("Yer yoxdur"))
{
    Console.WriteLine("Xəta: Diskdə yer qalmayıb!");
}
catch (UnauthorizedAccessException)
{
    Console.WriteLine("Xəta: faylı yazmaq üçün icazə yoxdur. Admin kimi başladın.");
}
catch (IOException ex)
{
    Console.WriteLine("Başqa disk xətası: " + ex.Message);
}
Müxtəlif catch tipləri və filterlərin birləşməsi

Burada həm filter, həm də error tiplərinə görə ayırma istifadə edirik. Belə çeviklik xüsusilə mürəkkəb tətbiqlərdə, tez-tez baş verən error-lara informativ reaksiya vermək üçün çox dəyərlidir.

4. Filterlərin və çoxlu catch-ların özəllikləri və "tələləri"

  • catch filteri exception dəyişənindən (ex) istifadə edə bilər, amma onu dəyişə bilməz.
  • Əgər when içində exception atsan, bu exception həmin catch tərəfindən "tutulmayacaq" — o, stack boyunca yuxarı gedəcək, sanki filter yox idi.
  • Filterin məntiqi artıq kontraktın bir hissəsidir: layihədəki komanda yoldaşın bilməlidir ki, hər IOException tutulmayacaq — yalnız şərt ödənərsə tutulacaq.
  • Əgər bütün metod üçün yalnız bir catch və içində filter istifadə edirsənsə, bəzi "artıq" exception-ları ümumiyyətlə tuta bilməyəcəksən. Şübhən varsa — ayrıca, açıq bloklardan istifadə et.
  • Böyük tətbiqlərdə filterlərdən mərkəzləşdirilmiş məntiq üçün istifadə etmək olar, məsələn, yalnız kritik error-ları log etmək üçün.

5. İntervü və real iş üçün ssenarilər

Filterləri və çoxlu catch bloklarını bilmək — təkcə gözəllik və ya clean code üçün deyil. Bu, real bacarıqdır və intervülərdə, xüsusilə böyük, mürəkkəb, paylanmış tətbiqlərin dəstəyi ilə bağlı vəzifələrdə səndən tələb oluna bilər.

Nümunə suallar:

  • C#-da fayl oxuma error-larını necə idarə etmək olar ki, müxtəlif situasiyalar üçün (fayl yoxdur, disk məşğuldur, data korlanıb) fərqli mesajlar göstərilsin?
  • Ümumi catch (Exception) bloku qoyanda vacib error-u necə "boğmamaq" olar?
  • catch filteri nə üçündür? Onun içində throw ola bilərmi?
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Çoxsaylı `catch` istifadə edərək istisnaların işlənməsi
Çoxsaylı `catch` istifadə edərək istisnaların işlənməsi
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
`catch` filtrlərindən istifadə
`catch` filtrlərindən istifadə
1
Sorğu/viktorina
, səviyyə, dərs
Əlçatan deyil
İstisnalarla tanışlıq
Çağırış steki və öz istisnalarını yaratmaq
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION