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.