Bagikan melalui


Membuat dan melempar pengecualian

Pengecualian digunakan untuk menunjukkan bahwa terjadi kesalahan saat menjalankan program. Objek pengecualian yang menjelaskan kesalahan dibuat lalu dilemparkan dengan pernyataan atau ekspresi throw. Runtime kemudian mencari handler pengecualian yang paling kompatibel.

Programmer harus melemparkan pengecualian ketika satu atau beberapa kondisi berikut ini benar:

  • Metode ini tidak dapat menyelesaikan fungsionalitas yang ditentukan. Misalnya, jika parameter ke metode memiliki nilai yang tidak valid:

    static void CopyObject(SampleClass original)
    {
        _ = original ?? throw new ArgumentException("Parameter cannot be null", nameof(original));
    }
    
  • Pemanggilan yang tidak sesuai terhadap sebuah objek dilakukan berdasarkan keadaan objek. Salah satu contohnya mungkin mencoba menulis ke file baca-saja. Dalam kasus di mana status objek tidak mengizinkan operasi, berikan instans InvalidOperationException atau objek berdasarkan turunan kelas ini. Kode berikut adalah contoh metode yang melemparkan objek InvalidOperationException:

    public class ProgramLog
    {
        FileStream logFile = null!;
        public void OpenLog(FileInfo fileName, FileMode mode) { }
    
        public void WriteLog()
        {
            if (!logFile.CanWrite)
            {
                throw new InvalidOperationException("Logfile cannot be read-only");
            }
            // Else write data to the log and return.
        }
    }
    
  • Ketika sebuah argumen pada metode menyebabkan pengecualian. Dalam hal ini, pengecualian asli harus ditangkap dan instans ArgumentException harus dibuat. Pengecualian asli harus diteruskan ke konstruktor ArgumentException sebagai parameter InnerException:

    static int GetValueFromArray(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch (IndexOutOfRangeException e)
        {
            throw new ArgumentOutOfRangeException(
                "Parameter index is out of range.", e);
        }
    }
    

    Nota

    Contoh sebelumnya menunjukkan cara menggunakan properti InnerException. Ini sengaja disederhanakan. Dalam praktiknya, Anda harus memeriksa bahwa indeks berada dalam rentang sebelum menggunakannya. Anda dapat menggunakan teknik membungkus pengecualian ini ketika anggota parameter melemparkan pengecualian yang tidak dapat Anda antisipasi sebelum memanggil anggota.

Pengecualian berisi properti bernama StackTrace. String ini berisi nama metode pada tumpukan panggilan saat ini, bersama dengan nama file dan nomor baris tempat pengecualian dilemparkan untuk setiap metode. Objek StackTrace dibuat secara otomatis oleh runtime bahasa umum (CLR) dari titik pernyataan throw, sehingga pengecualian harus dilemparkan dari titik di mana pelacakan tumpukan harus dimulai.

Semua pengecualian berisi properti bernama Message. String ini harus diatur untuk menjelaskan alasan pengecualian. Informasi yang sensitif terhadap keamanan tidak boleh dimasukkan ke dalam teks pesan. Selain Message, ArgumentException berisi properti bernama ParamName yang harus diatur ke nama argumen yang menyebabkan pengecualian terjadi. Dalam setter properti, ParamName harus disetel ke value.

Metode publik dan terlindungi melemparkan pengecualian setiap kali mereka tidak dapat menyelesaikan fungsi yang dimaksudkan. Kelas pengecualian yang dilemparkan adalah pengecualian paling spesifik yang tersedia yang sesuai dengan kondisi kesalahan. Pengecualian ini harus didokumentasikan sebagai bagian dari fungsionalitas kelas, dan kelas turunan atau pembaruan ke kelas asli harus mempertahankan perilaku yang sama untuk kompatibilitas mundur.

Hal-hal yang perlu dipertimbangkan saat melemparkan pengecualian

Daftar berikut mengidentifikasi praktik yang perlu dipertimbangkan saat melempar pengecualian:

  • Jangan gunakan pengecualian untuk mengubah alur program sebagai bagian dari eksekusi biasa. Gunakan pengecualian untuk melaporkan dan menangani kondisi kesalahan.
  • Pengecualian tidak boleh dikembalikan sebagai nilai return atau parameter, tetapi harus dilemparkan.
  • Jangan melemparkan System.Exception, System.SystemException, System.NullReferenceException, atau System.IndexOutOfRangeException sengaja dari kode sumber Anda sendiri.
  • Jangan membuat pengecualian yang dapat dilemparkan dalam mode debug tetapi bukan mode rilis. Untuk mengidentifikasi kesalahan run-time selama fase pengembangan, gunakan Debug Assert sebagai gantinya.

Pengecualian dalam metode pengembalian tugas

Metode yang dideklarasikan dengan pengubah async memiliki beberapa pertimbangan khusus dalam hal pengecualian. Pengecualian yang dilemparkan dalam metode async disimpan dalam tugas yang dikembalikan dan tidak muncul sampai, misalnya, tugas tersebut ditunggu. Untuk informasi selengkapnya tentang pengecualian tersimpan, lihat pengecualian Asinkron.

Kami menyarankan agar Anda memvalidasi argumen dan melemparkan pengecualian yang sesuai, seperti ArgumentException dan ArgumentNullException, sebelum memasukkan bagian asinkron dari metode Anda. Artinya, pengecualian validasi ini harus muncul secara sinkron sebelum pekerjaan dimulai. Cuplikan kode berikut menunjukkan contoh di mana, jika pengecualian dilemparkan, pengecualian ArgumentException akan muncul secara sinkron, sedangkan InvalidOperationException akan disimpan dalam tugas yang dikembalikan.

// Non-async, task-returning method.
// Within this method (but outside of the local function),
// any thrown exceptions emerge synchronously.
public static Task<Toast> ToastBreadAsync(int slices, int toastTime)
{
    if (slices is < 1 or > 4)
    {
        throw new ArgumentException(
            "You must specify between 1 and 4 slices of bread.",
            nameof(slices));
    }

    if (toastTime < 1)
    {
        throw new ArgumentException(
            "Toast time is too short.", nameof(toastTime));
    }

    return ToastBreadAsyncCore(slices, toastTime);

    // Local async function.
    // Within this function, any thrown exceptions are stored in the task.
    static async Task<Toast> ToastBreadAsyncCore(int slices, int time)
    {
        for (int slice = 0; slice < slices; slice++)
        {
            Console.WriteLine("Putting a slice of bread in the toaster");
        }
        // Start toasting.
        await Task.Delay(time);

        if (time > 2_000)
        {
            throw new InvalidOperationException("The toaster is on fire!");
        }

        Console.WriteLine("Toast is ready!");

        return new Toast();
    }
}

Menentukan kelas pengecualian

Program dapat melempar kelas pengecualian yang telah ditentukan sebelumnya di namespace System (kecuali jika sebelumnya dicatat), atau membuat kelas pengecualian mereka sendiri dengan berasal dari Exception. Kelas turunan harus menentukan setidaknya tiga konstruktor: satu konstruktor tanpa parameter, satu yang mengatur properti pesan, dan yang mengatur properti Message dan InnerException. Misalnya:

[Serializable]
public class InvalidDepartmentException : Exception
{
    public InvalidDepartmentException() : base() { }
    public InvalidDepartmentException(string message) : base(message) { }
    public InvalidDepartmentException(string message, Exception inner) : base(message, inner) { }
}

Tambahkan properti baru ke kelas pengecualian saat data yang mereka berikan berguna untuk menyelesaikan pengecualian. Jika properti baru ditambahkan ke kelas pengecualian turunan, ToString() harus ditimpa untuk mengembalikan informasi tambahan.

Spesifikasi bahasa C#

Untuk informasi selengkapnya, lihat Pengecualian dan Pernyataan throw dalam Spesifikasi Bahasa C#. Spesifikasi bahasa adalah sumber definitif untuk sintaks dan penggunaan C#.

Lihat juga