Gunakan pengecualian
Di C#, kesalahan dalam program pada saat dijalankan disebarkan melalui program dengan menggunakan mekanisme yang disebut pengecualian. Pengecualian dihasilkan oleh kode yang mengalami kesalahan dan ditangkap oleh kode yang dapat memperbaiki kesalahan. Pengecualian dapat dihasilkan oleh runtime .NET atau dengan kode dalam program. Setelah pengecualian dilemparkan, ia menyebarkan tumpukan panggilan hingga ada pernyataan catch
untuk pengecualian. Pengecualian yang tidak tertangkap ditangani oleh penanganan pengecualian umum yang disediakan oleh sistem yang menampilkan kotak dialog.
Pengecualian diwakili oleh kelas turunan dari Exception. Kelas ini mengidentifikasi jenis pengecualian dan berisi properti yang memiliki terperinci tentang pengecualian. Melemparkan pengecualian melibatkan pembuatan instans kelas turunan pengecualian, secara opsional mengonfigurasi properti pengecualian, lalu menghasilkan objek dengan menggunakan kata kunci throw
. Misalnya:
class CustomException : Exception
{
public CustomException(string message)
{
}
}
private static void TestThrow()
{
throw new CustomException("Custom exception in TestThrow()");
}
Setelah pengecualian dilemparkan, runtime memeriksa pernyataan saat ini untuk melihat apakah itu berada dalam blok try
. Jika ya, setiap blok catch
yang terkait dengan blok try
akan diperiksa untuk melihat apakah mereka dapat menangkap pengecualian. blok Catch
biasanya menentukan jenis pengecualian; jika jenis blok catch
sama dengan pengecualian, atau kelas dasar pengecualian, blok catch
dapat menangani metode. Misalnya:
try
{
TestThrow();
}
catch (CustomException ex)
{
System.Console.WriteLine(ex.ToString());
}
Jika pernyataan yang menghasilkan pengecualian tidak berada dalam blok try
atau jika blok try
yang mengapitnya tidak memiliki blok catch
yang cocok, runtime memeriksa metode panggilan untuk pernyataan try
dan blok catch
. Runtime melanjutkan tumpukan panggilan, mencari blok catch
yang kompatibel. Setelah blok catch
ditemukan dan dijalankan, kontrol diteruskan ke pernyataan berikutnya setelah blok catch
tersebut.
Pernyataan try
dapat berisi lebih dari satu blok catch
. Pernyataan catch
pertama yang dapat menangani pengecualian akan dijalankan; pernyataan catch
berikut meskipun kompatibel akan diabaikan. Pesanan menangkap blok dari yang paling spesifik (atau paling turunan) ke yang paling tidak spesifik. Misalnya:
using System;
using System.IO;
namespace Exceptions
{
public class CatchOrder
{
public static void Main()
{
try
{
using (var sw = new StreamWriter("./test.txt"))
{
sw.WriteLine("Hello");
}
}
// Put the more specific exceptions first.
catch (DirectoryNotFoundException ex)
{
Console.WriteLine(ex);
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
}
// Put the least specific exception last.
catch (IOException ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Done");
}
}
}
Sebelum blok catch
dijalankan, runtime akan memeriksa blok finally
. Dengan blok Finally
, programmer dapat membersihkan status ambigu yang dapat ditinggalkan dari blok try
yang dibatalkan, atau untuk melepaskan sumber daya eksternal apa pun (seperti handel grafis, koneksi database, atau aliran file) tanpa menunggu pengumpul sampah di runtime untuk menyelesaikan objek. Misalnya:
static void TestFinally()
{
FileStream? file = null;
//Change the path to something that works on your machine.
FileInfo fileInfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
file?.Close();
}
try
{
file = fileInfo.OpenWrite();
Console.WriteLine("OpenWrite() succeeded");
}
catch (IOException)
{
Console.WriteLine("OpenWrite() failed");
}
}
Jika WriteByte()
menghasilkan pengecualian, kode di blok try
kedua yang mencoba membuka kembali file akan gagal jika file.Close()
tidak dipanggil, dan file akan tetap terkunci. Karena blok finally
dijalankan bahkan jika pengecualian dilemparkan, blok finally
dalam contoh sebelumnya memungkinkan file ditutup dengan benar dan membantu menghindari kesalahan.
Jika tidak ditemukan blok catch
yang kompatibel pada tumpukan panggilan setelah pengecualian dihasilkan, salah satu dari tiga hal ini akan terjadi:
- Jika pengecualian berada dalam finalizer, finalizer dibatalkan dan finalizer dasar, jika ada, dipanggil.
- Jika tumpukan panggilan berisi konstruktor statis, atau penginisialisasi bidang statis, TypeInitializationException dihasilkan, dengan pengecualian asli yang ditetapkan ke properti InnerException pengecualian baru.
- Jika awal utas tercapai, utas akan dihentikan.