Mengapa akhirnya digunakan di C #?

189

Apa pun yang ada di dalam akhirnya blok dieksekusi (hampir) selalu, jadi apa perbedaan antara memasukkan kode ke dalamnya atau membiarkannya tidak tertutup?

Rodrigo
sumber
3
Apa maksud Anda dengan membiarkannya tidak tertutup?
Ramesh
5
Dan apa yang Anda maksud dengan "(hampir)"?
Beska
49
Jika Anda mencabut kabel daya saat mesin menjalankan klausa coba, klausa terakhir tidak akan dipanggil.
Dour High Arch
5
lol, ya, itu benar, tetapi Anda tidak dapat benar-benar kode untuk itu, bukan?
Ed S.
2
@ Id: Gunakan transaksi. Klausa coba Anda harus membuat semacam perubahan sementara atau dalam memori yang dapat bertahan dalam satu perubahan atomik tunggal pada klausa akhirnya. Ini jarang mudah dan mungkin memerlukan perangkat keras khusus.
Dour High Arch

Jawaban:

405

Kode di dalam blok akhirnya akan dieksekusi terlepas dari apakah ada pengecualian atau tidak. Ini sangat berguna ketika datang ke fungsi rumah tangga tertentu yang Anda harus selalu jalankan seperti menutup koneksi.

Sekarang, saya menduga pertanyaan Anda adalah mengapa Anda harus melakukan ini:

try
{
    doSomething();
}
catch
{
    catchSomething();
}
finally
{
    alwaysDoThis();
}

Kapan Anda bisa melakukan ini:

try
{
    doSomething();
}
catch
{
    catchSomething();
}

alwaysDoThis();

Jawabannya adalah bahwa sering kali kode di dalam pernyataan tangkap Anda akan rethrow pengecualian atau keluar dari fungsi saat ini. Dengan kode yang terakhir, "alwaysDoThis ();" panggilan tidak akan dieksekusi jika kode di dalam pernyataan hasil tangkapan mengembalikan atau melempar pengecualian baru.

Kevin Pang
sumber
3
Hmm. Sangat mirip dengan apa yang saya katakan, tetapi lebih jelas dan lebih tepat. Pasti +1.
Beska
46
ini berlaku untuk "kembali" di dalam blok coba {} juga.
Lucas
4
sebenarnya, ini berlaku bahkan tanpa blok {} catch (hanya coba / akhirnya, membiarkan pengecualian muncul)
Lucas
lebih baik daripada milikku, sedang bekerja dan tidak ingin menghabiskan sepuluh menit untuk menjawabnya secara rinci. +1
Matt Briggs
2
Ya, ini persis apa yang ada dalam pikiran saya: D Sekarang saya memahaminya.
Rodrigo
62

Sebagian besar keuntungan menggunakan try-akhirnya sudah ditunjukkan, tapi saya pikir saya akan menambahkan yang ini:

try
{
    // Code here that might throw an exception...

    if (arbitraryCondition)
    {
        return true;
    }

    // Code here that might throw an exception...
}
finally
{
    // Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}

Perilaku ini membuatnya sangat berguna dalam berbagai situasi, terutama ketika Anda perlu melakukan pembersihan (membuang sumber daya), meskipun blok penggunaan sering lebih baik dalam kasus ini.

Noldorin
sumber
2
Ini benar-benar satu-satunya alasan saya akhirnya menggunakan
Christopher Townsend
12

kapan saja Anda menggunakan permintaan kode yang tidak dikelola seperti pembaca aliran, permintaan db, dll; dan Anda ingin menangkap pengecualian kemudian gunakan try catch akhirnya dan tutup aliran, pembaca data, dll. pada akhirnya, jika Anda tidak melakukannya ketika kesalahan koneksi tidak bisa ditutup, ini benar-benar buruk dengan permintaan db

 SqlConnection myConn = new SqlConnection("Connectionstring");
        try
        {
            myConn.Open();
            //make na DB Request                
        }
        catch (Exception DBException)
        {
            //do somehting with exception
        }
        finally
        {
           myConn.Close();
           myConn.Dispose();
        }

jika Anda tidak ingin menangkap kesalahan maka gunakan

 using (SqlConnection myConn = new SqlConnection("Connectionstring"))
        {
            myConn.Open();
            //make na DB Request
            myConn.Close();
        }

dan objek koneksi akan dibuang secara otomatis jika ada kesalahan, tetapi Anda tidak menangkap kesalahan tersebut

Bob The Janitor
sumber
2
Buang () juga akan Tutup () koneksi, tidak perlu memanggil keduanya. Tutup () TIDAK Dipose (), Anda dapat membuka kembali koneksi.
Lucas
Bagus, terima kasih telah menyebutkan menggunakan. Saya harus menjawab, jika tidak.
Dan Rosenstark
11

Karena akhirnya akan dieksekusi bahkan jika Anda tidak menangani pengecualian di blok tangkap.

Matt Briggs
sumber
7

Akhirnya pernyataan dapat dieksekusi bahkan setelah kembali.

private int myfun()
{
    int a = 100; //any number
    int b = 0;
    try
    {
        a = (5 / b);
        return a;
    }
    catch (Exception ex)
    {
        Response.Write(ex.Message);
        return a;
    }

 //   Response.Write("Statement after return before finally");  -->this will give error "Syntax error, 'try' expected"
    finally
    {
      Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
    } 

    Response.Write("Statement after return after finally");  // -->Unreachable code
}
Prateek Gupta
sumber
7

finally, seperti dalam:

try {
  // do something risky
} catch (Exception ex) {
  // handle an exception
} finally {
  // do any required cleanup
}

adalah peluang yang dijamin untuk mengeksekusi kode setelah try..catchblok Anda , terlepas dari apakah Anda mencoba atau tidak melempar pengecualian.

Itu membuatnya sempurna untuk hal-hal seperti melepaskan sumber daya, koneksi db, file menangani, dll.

David Alpert
sumber
3
Semua contoh tersebut biasanya lebih baik disajikan dengan blok penggunaan, tetapi itu tidak benar-benar mengurangi jawaban Anda.
Joel Coehoorn
4

saya akan menjelaskan penggunaan akhirnya dengan contoh pembaca file Contoh

  • tanpa menggunakan akhirnya
try{

  StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
  Console.WriteLine(strReader.ReadeToEnd());
  StreamReader.Close();
}
catch (Exception ex)
{
  Console.WriteLine(ex.Message);
}

dalam contoh di atas jika file bernama Data.txt hilang, pengecualian akan dibuang dan akan ditangani tetapi pernyataan yang dipanggil StreamReader.Close();tidak akan pernah dieksekusi.
Karena sumber daya yang terkait dengan pembaca ini tidak pernah dirilis.

  • Untuk mengatasi masalah di atas, akhirnya kami gunakan
StreamReader strReader = null;
try{
    strReader = new StreamReader(@"C:\Ariven\Project\Data.txt");
    Console.WriteLine(strReader.ReadeToEnd());
}
catch (Exception ex){
    Console.WriteLine(ex.Message);
}
finally{
    if (strReader != null){
        StreamReader.Close();
    }
}

Selamat Coding :)

Catatan: "@" digunakan untuk membuat string kata demi kata , untuk menghindari kesalahan "Urutan keluar yang tidak dikenal". Simbol @ berarti membaca string itu secara harfiah, dan tidak menafsirkan karakter kontrol sebaliknya.

Ariven Nadar
sumber
2

Katakanlah Anda perlu mengatur kursor kembali ke pointer default daripada kursor menunggu (jam pasir). Jika pengecualian dilemparkan sebelum mengatur kursor, dan tidak langsung crash aplikasi, Anda bisa dibiarkan dengan kursor membingungkan.

Chris Doggett
sumber
2

Terkadang Anda tidak ingin menangani pengecualian (tanpa blok tangkapan), tetapi Anda ingin beberapa kode pembersihan dijalankan.

Sebagai contoh:

try
{
    // exception (or not)
}
finally
{
    // clean up always
}
markom
sumber
Jika pengecualian tidak tertangkap, eksekusi blok akhirnya tergantung pada apakah sistem operasi memilih untuk memicu operasi pelepasan pengecualian.
Vikas Verma
2

Blok akhirnya berguna untuk membersihkan semua sumber daya yang dialokasikan dalam blok coba serta menjalankan kode apa pun yang harus dijalankan bahkan jika ada pengecualian. Kontrol selalu diteruskan ke blok akhirnya terlepas dari bagaimana blok coba keluar.

cgreeno
sumber
1

Ahh ... kurasa aku mengerti apa yang kamu katakan! Butuh waktu sebentar ... Anda bertanya-tanya "mengapa menempatkannya di blok akhirnya alih-alih setelah blok akhirnya dan benar-benar di luar try-catch-akhirnya".

Sebagai contoh, itu mungkin karena Anda menghentikan eksekusi jika Anda melakukan kesalahan, tetapi Anda masih ingin membersihkan sumber daya, seperti file yang terbuka, koneksi database, dll.

Beska
sumber
1

Aliran Kontrol Blok Akhirnya adalah setelah blok Coba atau Tangkap.

[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]

dengan Pengecualian 1> 2> 3> 4> 5 jika 3 memiliki pernyataan Pengembalian 1> 2> 3> 4

tanpa Pengecualian 1> 2> 4> 5 jika 2 memiliki pernyataan pengembalian 1> 2> 4

Ranald Fong
sumber
0

Seperti disebutkan dalam dokumentasi :

Penggunaan umum tangkapan dan akhirnya bersama adalah untuk mendapatkan dan menggunakan sumber daya dalam blok uji coba, menangani keadaan luar biasa dalam blok tangkapan, dan melepaskan sumber daya di blok akhirnya.

Perlu juga membaca ini , yang menyatakan:

Setelah klausa tangkapan yang cocok ditemukan, sistem bersiap untuk mentransfer kontrol ke pernyataan pertama klausa tangkapan. Sebelum eksekusi klausa tangkapan dimulai, sistem terlebih dahulu mengeksekusi, agar, setiap klausa akhirnya yang terkait dengan pernyataan coba lebih bersarang daripada yang menangkap pengecualian.

Jadi jelas bahwa kode yang berada dalam finallyklausa akan dieksekusi bahkan jika catchklausa sebelumnya memiliki returnpernyataan.

Nexaspx
sumber