# finally

Bundan avvalgi darslarimizda try/catch bloki haqida yaxshigina ma’lumotlarni qo’lga kiritigansiz degan umidda ushbu bloklarning finalini ta’minlovchi finally haqida so’z yuritamiz. Dasturlar ba’zida istisno holatlari bilan yakunlangan bo’lishi mumkin, ya’ni dastur tanasining **try { ... }** bloki bajarilmasdan aksincha, dastur **catch { ... }** bloki ichida yakunlangan. Ammo ba’zida dastur xatolik holatiga tushguniga qadar biror yopilishi kerak bo’lgan fayl yoki tarmoqni ochgan bo’lishi mumkin. Bunday ochilgan tarmoq va fayllarni yopish uchun **finally { ... }** blokidan foydalaniladi.

{% hint style="info" %}
**finally** bloki har qanday istisno holati (catch) yoki try bloki bajarilishidan qat’iy nazar bajariladi.
{% endhint %}

"Sizlar nima qilsangiz ham men baribir so’ngida o’z so’zimni aytaman" shiori ostida ish ko’ruvchi blokni amaliy misollarda qaraymiz:

```csharp
try
{
    int a = 0;
    int b = 5;
    Console.WriteLine(b/a);
}

catch(DivideByZeroException)
{
    Console.WriteLine("0 ga bo'lish mumkin emas !");
}

finally
{
    Console.WriteLine("Dastur ishlashi tugallandi.");
} 
```

Yuqoridagi holatda dasturning istisno holati bajarilgach, finally bloki ichidagi kod o’z ishini boshlaydi. Agar o’zgaruvchilarning qiymatlarini misol uchun a = 2, b = 4 tarzida o’zgartirsak, u holda, dasturning catch bloki bajarilmaydi, lekin so’ngida baribir finally bloki ichidagi kod bajarilishini ko’rish mumkin.

Endi yana bir misolni qaraymiz. Faraz qilaylik, ma’lum katalogdagi fayldagi ma’lumotlarni boshqa faylning ma’lumotlariga qo’shish kerak:

```csharp
StreamReader reader = null;
StreamWriter writer = null;
try
{
    reader = new StreamReader(File.Open(@"C:\Users\Public\Documents\file1.txt", FileMode.Open));
    writer = new StreamWriter(File.Open(@"C:\Users\Public\Documents\file2.txt", FileMode.Append, FileAccess.Write));
    while (reader.Peek() != -1)
    {
        writer.WriteLine(reader.ReadLine());
    }

}

catch(Exception ex)
{
     Console.WriteLine(ex);
}
```

Yuqoridagi holatda *file1.txt* faylining ma’lumotlari *file2.txt* ga qo’shilmoqda. Agar *file1.txt* dagi ma’lumotlarni o’qishda yoki *file2.txt* ga ma’lumotlarni yozishda qandaydir xatolik ro’y bersa, dasturning catch bloki bajariladi va xatolik to’g’risida xabar qilinadi. Lekin shuni unutmaslik kerak-ki, dastur catch holatiga tushganda ikkala fayllarning ham holati ochiq holda. Endi ushbu dasturga finally bloki ichida bu ikkala faylni ham yopuvchi kodni yozish eng to’g’ri qaror:

```csharp
StreamReader reader = null;
StreamWriter writer = null;
try
{
    reader = new StreamReader(File.Open(@"C:\Users\Public\Documents\file1.txt", FileMode.Open));
    writer = new StreamWriter(File.Open(@"C:\Users\Public\Documents\file2.txt", FileMode.Append, FileAccess.Write));
    while (reader.Peek() != -1)
    {
        writer.WriteLine(reader.ReadLine());
    }
}

catch(Exception ex)
{
    Console.WriteLine(ex);
}

finally
{
    if(reader != null)
    {
        reader.Close();
    }

    if(writer != null)
    {
        writer.Close();
    }
}

Console.ReadKey(); 
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.dot-net.uz/c-.net/basic/essential/finally.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
