Penanganan
Eksepsi
2.1 Pengantar
Eksepsi merupakan suatu indikasi terjadinya
suatu masalah selama eksekusi program. Penanganan eksepsi memampukan Anda untuk
menciptakan aplikasi yang bisa menyelesaikan (menangani) eksepsi. Pada banyak
kasus, penanganan suatu eksepsi membolehkan program untuk melanjutkan eksekusi,
layaknya seperti tidak ada masalah. Fitur yang disajikan pada bab ini membantu
Anda dalam menulis program yang handal dan toleran-kesalahan, yang dapat
menangani masalah dan melanjutkan eksekusi atau berhenti secara normal.
Penanganan eksepsi C# didasarkan pada kerja dari Andrew Koenig dan Bjarne
Stroustrup.
2.2
Contoh: Pembagian Nol Tanpa Eksepsi
Pertama, akan didemonstrasikan apa yang
terjadi ketika error terjadi dalam suatu aplikasi yang tidak menggunakan
penanganan eksepsi. Gambar 2.1 meminta pengguna untuk memasukkan dua integer,
yang menghitung hasil pembagian atas dua
integer dan menghasilkan nilai balik berupa suatu nilai int. Pada contoh ini, Anda akan melihat bahwa eksepsi dilempar
ketika suatu metode mendeteksi adanya masalah dan tidak mampu mengatasinya.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//
Gambar 2.1: PembagianNolTanpaEksepsi.cs
// Pembagian
integer tanpa penanganan eksepsi.
using
System;
class
PembagianNolTanpaEksepsi
{
static
void Main()
{
// membaca numerator dan denominator
Console.Write( "Silahkan masukkan sebuah numerator
integer: " );
int numerator = Convert.ToInt32( Console.ReadLine() );
Console.Write("Silahkan masukkan sebuah denominator
integer: ");
int
denominator = Convert.ToInt32( Console.ReadLine() );
// membagi dua integer, kemudian
menampilkan hasilnya
int
hasil = numerator / denominator;
Console.WriteLine( "\nHasil: {0:D} / {1:D} = {2:D}",
numerator, denominator, hasil );
} // akhir Main
} // akhir kelas PembagianNolTanpaEksepsi
|
Silahkan masukkan sebuah numerator integer: 100
Silahkan masukkan sebuah denominator integer: 7
Hasil: 100 / 7 = 14
|
Silahkan masukkan sebuah numerator integer: 100
Silahkan masukkan sebuah denominator integer: 0
Unhandled Exception: System.DivideByZeroException:
Attempted
to divide by zero.
at
PembagianNolTanpaEksepsi.Main() in e:\
Projects
Visual C#\PembagianNolTanpaEksepsi\
PembagianNolTanpaEksepsi\PembagianNolTanpaEksepsi.cs:line
16
|
Silahkan masukkan sebuah numerator
integer: 100
Silahkan masukkan sebuah denominator
integer: jogja
Unhandled Exception: System.FormatException:
Input
string was not in a correct format.
at
System.Number.StringToNumber(String str, NumberStyles options,
NumberBuffer&
number, NumberFormatInfo info, Boolean parseDecimal)
at
System.Number.ParseInt32(String s, NumberStyles style,
NumberFormatInfo
info)
at
System.Convert.ToInt32(String value)
at
PembagianNolTanpaEksepsi.Main() in e:\Projects Visual C#
\PembagianNolTanpaEksepsi\PembagianNolTanpaEksepsi\
PembagianNolTanpaEksepsi.cs:line
13
|
Menganalisa Hasil
Contoh eksekusi pertama pada Gambar 2.1
menunjukkan pembagian integer yang sukses. Eksekusi kedua, pengguna memasukan
nilai 0 sebagai denominator. Beberapa baris informasi ditampilkan sebagai respon
terhadap masukan yang tidak valid. Informasi tersebut dikenal dengan jejak
tumpukan (stack trace), yang
mencantumkan nama eksepsi (System.DivideByZeroException) dalam pesan deskriptif yang mengindikasikan
terjadinya masalah dan menampilkan tumpukan pemanggilan metode pada saat
masalah terjadi. Jejak tumpukan menyertakan jalur eksekusi yang mengarah ke
eksepsi metode demi metode. Ini akan membantu Anda untuk mendebug program.
Baris pertama menspesifikasi bahwa suatu DivideByZeroException telah terjadi. Teks setelah nama eksekusi (“Attempted
to divide by zero”) mengindikasikan
bahwa eksepsi ini terjadi sebagai akibat dari percobaan untuk membagi dengan
nol. C# tidak mengijinkan pembagian oleh nol dalam aritmatika integer. Ketika
hal ini terjadi, C# akan melemparkan suatu DivideByZeroException. Tetapi C# membolehkan pembagian oleh nol
menggunakan nilai-nilai pecahan. Kalkulasi semacam itu akan menghasilkan nilai
tak-terhingga positif atau negaitif, yang direpresentasikan dalam C# sebagai
konstanta Double.PositiveInfinity
atau konstanta Double.NegativeInfinity,
tergantung dari apakah numerator positif atau negatif.
Setiap baris “at” pada jejak tumpukan mengindikasikan sebuah baris kode pada
metode tertentu yang dieksekusi ketika eksepsi terjadi. Baris “at” memuat namespace, kelas, dan metode
dimana di dalamnya eksepsi terjadi (PembagianNolTanpaEksepsi.Main()), lokasi dan nama file yang memuat
kode (e:\Projects Visual C#\PembagianNolTanpaEksepsi\
PembagianNolTanpaEksepsi\PembagianNolTanpaEksepsi.cs), dan nomor baris (:line 16) dimana eksekusi terjadi. Pada
kasus ini, jejak tumpukan mengindikasikan bahwa eksepsi DivideByZeroException terjadi ketika program mengeksekusi baris
16 pada metode Main. Baris pertama “at” pada jejak tumpukan mengindikasikan
titik lempar (throwing point)
eksepsi, yaitu titik awal di mana eksepsi terjadi (baris 16 pada Main). Informasi ini memudahkan Anda
untuk melihat di mana eksepsi berawal, dan pemanggilan metode apa yang
dilakukan pada program.
Pada contoh eksekusi ketiga, pengguna
memasukkan string “jogja” sebagai
denominator. Perhatikan kembali bahwa jejak tumpukan ditampilkan. Hal ini
menginformasikan Anda bahwa suatu FormatException
telah terjadi. Kode program yang membaca nilai numerik mengasumsikan bahwa
pengguna akan memasukkan nilai integer. Tetapi, pengguna kadangkala melakukan
kesalahan dan memasukkan nilai non-integer. Suatu FormatException (namespace
System) terjadi ketika metode ToInt32 dari kelas Convert menerima suatu string
yang tidak merepresentasikan suatu integer yang valid. Dimulai dari baris
terakhir “at” pada jejak tumpukan,
Anda melihat bahwa eksepsi dideteksi pada baris 13 dari metode Main. Jejak tumpukan juga menunjukkan
metode-metode lain yang terlibat dengan eksepsi yang sedang dilempar. Untuk
melakukan tugasnya, Convert.ToInt32
memanggil metode Number.ParseInt32,
yang juga memanggil Number.StringToNumber.
Titik lempar terjadi pada Number.StringToNumber,
seperti diindikasikan oleh baris pertama “at”
pada jejak tumpukan.
Pada dua contoh eksekusi pada Gambar 2.1,
program berhenti ketika eksekusi terjadi dan jejak tumpukan ditampilkan. Ini
tidak selalu terjadi, karena kadangkala program berlanjut mengeksekusi meskipun
eksepsi terjadi dan jejak tumpukan ditampilkan. Pada contoh berikutnya akan
didemonstrasikan bagaimana menangani eksepsi untuk memampukan sebuah program
diekseksi secara normal.
2.3
Contoh: Penanganan DivideByZeroException dan FormatException
Aplikasi pada Gambar 2.2, yang didasarkan
pada Gambar 2.1, menggunakan penanganan eksepsi untuk memproses sembarang DivideByZeroException
dan FormatException yang dibangkitkan. Versi aplikasi ini
menggunakan penanganan eksepsi sehingga jika pengguna melakukan kesalahan,
program akan menangkap dan menangani eksepsi, sehingga pada kasus ini, pengguna
dapat mengentri masukan kembali. Aplikasi membaca dua integer dari pengguna
(baris 18-21). Jika pengguna menyediakan dua integer sebagai masukan dan tidak
menetapkan 0 sebagai denominator, maka baris 25 akan melakukan pembagian dan
baris 28-29 menampilkan hasilnya. Namun, jika pengguna mengentrikan masukan
tak-integer atau menyediakan 0 sebagai denominator, maka eksepsi akan terjadi.
Program ini mendemonstrasikan bagaimana menangkap dan menangani eksepsi semacam
itu. Pada kasus ini, program akan menampilkan pesan error dan mengijinkan
pengguna untuk mengentrikan-ulang masukan.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
//
Gambar 2.2: PembagianNolDenganEksepsi.cs
//
Menangani eksepsi FormatException dan DivideByZeroException.
using
System;
class
PembagianNolDenganEksepsi
{
static
void Main( string[] args )
{
bool
loopLanjut = true; // menentukan
apakah tetap beriterasi
do
{
// membaca masukan pengguna dan menghitung hasil
bagi
try
{
//
Convert.ToInt32 membangkitkan FormatException
// jika
argumen tidak dapat dikonversi menjadi integer
Console.Write(
"Masukkan sebuah numerator
integer: " );
int numerator = Convert.ToInt32(
Console.ReadLine() );
Console.Write(
"Masukkan sebuah denominator
integer: " );
int denominator = Convert.ToInt32(
Console.ReadLine() );
//
pembagian membangkitkan DivideByZeroException
// jika
denominator bernilai 0
int hasil = numerator / denominator;
//
menampilkan hasil
Console.WriteLine( "\nHasil:
{0} / {1} = {2}",
numerator,
denominator, hasil );
loopLanjut
= false;
} // akhir try
catch ( FormatException eksepsiFormat )
{
Console.WriteLine(
"\n" + eksepsiFormat.Message );
Console.WriteLine(
"Anda harus memasukkan dua
integer. Silahkan coba lagi.\n"
);
} // akhir catch
catch ( DivideByZeroException eksepsiPembagianDenganNol )
{
Console.WriteLine(
"\n" + eksepsiPembagianDenganNol.Message );
Console.WriteLine(
"Nol tidak valid untuk
denominator. Silahkan coba lagi.\n"
);
} // akhir catch
} while ( loopLanjut ); // akhir do...while
} // akhir Main
} // akhir kelas PembagianNolDenganEksepsi
|
Silahkan masukkan sebuah numerator integer: 100
Silahkan masukkan sebuah denominator integer: 7
Hasil: 100 / 7 = 14
|
Masukkan sebuah numerator integer: 100
Masukkan sebuah denominator integer: 0
Attempted to divide by zero.
Nol tidak valid untuk denominator. Silahkan coba
lagi.
|
Masukkan sebuah numerator integer:
100
Masukkan sebuah denominator integer:
jogja
Input string was not in a correct
format.
Anda harus memasukkan dua integer. Silahkan coba
lagi.
|
Contoh-Contoh Keluaran
Sebelum mendiskusikan detil program,
akan didiskusikan lebih dahulu contoh-contoh keluaran program pada Gambar 2.2.
Contoh keluaran program yang pertama menunjukkan perhitungan yang sukses dimana
di dalamnya pengguna memasukkan numerator 100 dan denominator 7. Hasil (14)
merupakan sebuah int, karena
pembagian integer selalu menghasilkan hasil int. Contoh keluaran program yang kedua mendemonstrasikan hasil
dari percobaan pembagian dengan nol. Dalam aritmatika integer, pembagian nol
akan membangkitkan eksepsi DivideByZeroException
jika denominator bernilai nol. Program mendeteksi eksepsi dan menampilkan
sebuah pesan error yang mengindikasikan percobaan pembagian nol. Contoh
keluaran program yang terakhir menampilkan hasil dari pengentrian sebuah nilai
tak-int. Pada kasus ini, pengguna
memasukkan “jogja” sebagai
denominator. Program mencoba mengkonversi masukan string menjadi int
menggunakan metode Convert.ToInt32
(baris 19 dan 21). Jika argumen tidak dapat dikonversi menjadi int, maka metode akan melemparkan
eksepsi FormatException. Program
menangkap eksepsi dan menampilkan pesan error yang mengindikasikan bahwa
pengguna harus memasukkan dua int.
Cara Lain Untuk Mengkonversi String Menjadi Integer
Cara lain untuk memvalidasi masukan
adalah dengan menggunakan metode Int32.TryParse,
yang mengkonversi sebuah string
menjadi sebuah int jika
memungkinkan. Semua tipe numerik memiliki metode TryParse masing-masing. Metode itu memerlukan dua argumen, yaitu
satu berupa string yang akan
dikonversi dan yang lain adalah varibel yang di dalamnya nilai terkonversi akan
disimpan. Metode ini menghasilkan nilai balik true jika string dikonversi dengan sukses. Jika string tidak dapat dikonversi, maka
nilai 0 ditugaskan kepada argumen kedua, yang dilewatkan dengan referensi
sehingga nilainya dapat dimodifikasi pada metode pemanggil. Metode TryParse dapat dipakai untuk memvalidasi
masukan sehingga kode tidak perlu melemparkan eksepsi.
Kode di dalam Blok try
Baris 14-31 memuat suatu blok try, yang mengapit kode, yang mungkin,
akan melempar suatu eksepsi dan kode tersebut tidak akan dieksekusi jika
eksepsi terjadi (blok try akan
dilompati). Blok try memuat
katakunci try diikuti dengan suatu
blok kode yang diapit oleh sepasang kurung kurawal.
Beberapa statemen yang membaca integer dari
papanketik (baris 19 dan 21) masing-masing menggunakan metode Convert.ToInt32 untuk mengkonversi string menjadi int. Metode ini melempar eksepsi FormatException jika ia tidak berhasil mengkonversi string menjadi int. Jika baris 19 dan 21 mengkonversi nilai-nilai dengan benar
(tidak ada eksepsi terjadi), maka baris 25 akan membagi numerator dengan denominator
dan menugaskan hasilnya kepada variabel hasil.
Jika baris 25 tidak menyebabkan eksepsi dilempar, maka baris 28-29 akan
menampilkan hasil pembagian.
Menangkap Eksepsi
Kode penanganan-eksepsi berada di dalam
blok catch. Secara umum, ketika
sebuah eksepsi terjadi pada suatu blok try,
blok catch terkait akan menangkap
eksepsi tersebut dan menanganinya. Blok try
pada contoh ini diikuti oleh dua blok catch,
yaitu satu yang menangani eksepsi FormatException
(baris 32-37) dan satu lagi yang menangani eksepsi DivideByZeroException (baris 38-43). Blok catch menetapkan parameter eksepsi yang merepresentasikan eksepsi
yang akan ditanganinya. Blok catch
dapat menggunakan pengenal parameter (yang Anda pilih sendiri) untuk berinteraksi
dengan objek eksepsi yang ditangkap. Jika Anda tidak perlu menggunakan objek
eksepsi pada blok catch, maka
pengenal dari parameter eksepsi dapat diabaikan. Tipe parameter catch adalah tipe eksepsi yang akan
ditangani oleh blok catch. Secara
opsional, Anda bisa mencantumkan sebuah blok catch yang tidak menetapkan tipe eksepsi spesifik. Blok catch semacam itu akan menangkap semua
tipe eksepsi. Satu blok catch dan/
atau blok finally harus diikuti oleh
sedikitnya satu blok try.
Pada Gambar 2.2, blok catch yang pertama menangkap eksepsi FormatException (yang dilempar oleh
metode Convert.ToInt32), dan blok catch kedua menangkap eksepsi DivideByZero-Exception. Jika eksepsi
terjadi, program hanya akan mengeksekusi blok catch pertama yang sesuai. Kedua handler eksepsi pada contoh ini menampilkan pesan error. Jika salah
satu blok catch selesai dieksekusi,
kendali program akan berlanjut ke statemen pertama yang berada setelah blok
catch yang terakhir.
2.4
Blok finally
Program yang memperoleh tipe tertentu dari
sumberdaya harus mengembalikannya lagi kepada sistem secara ekplisit untuk
menghindari apa yang disebut dengan kebocoran sumberdaya. Dalam bahasa
pemrograman seperti C dan C++, kebocoran sumberdaya yang sering terjadi adalah
kebocoran memori. C# melakukan pengumpulan sampah secara otomatis terhadap
memori yang tidak lagi digunakan oleh program, sehingga menghindari kebanyakan
kasus kebocoran memori. Tetapi, beberapa tipe kebocoran tetap saja terjadi.
Sebagai contoh, koneksi file, koneksi database, dan koneksi jaringan yang tidak
ditutup secara tepat setelah tidak lagi dibutuhkan bisa dimanfaatkan oleh
program lain.
Blok finally
(yang memuat katakunci finally,
diikuti dengan kode yang diapit oleh sepasang kurung kurawal), kadangkala
disebut pula dengan klausa finally,
bersifat opsional. Jika blok ini ada, maka ia ditempatkan setelah blok catch terakhir. Jika tidak terdapat
satupun blok catch, maka blok finally ditempatkan setelah blok try.
Blok finally
akan dieksekusi tanpa memandang suatu eksepsi dilempar atau tidak di dalam
suatu blok try. Blok finally juga akan dieksekusi jika suatu
blok try keluar menggunakan statemen
return, break, atau continue
atau jika suatu blok try keluar
hanya karena kurung kurawal penutupnya. Blok finally tidak akan dieksekusi jika aplikasi keluar dari suatu blok
try dengan menggunakan statemen System.exit.
Karena blok finally hampir selalu dieksekusi, ia biasanya memuat kode pelepas
sumberdaya. Dimisalkan bahwa suatu sumberdaya dialokasikan di dalam suatu blok try. Jika tidak terjadi eksepsi, maka
blok catch akan dilompati dan
kendali program akan berlanjut untuk mengeksekusi blok finally, yang akan melepaskan sumberdaya yang dipakai. Jika suatu eksepsi
terjadi di dalam suatu blok try,
maka blok try itu akan berhenti.
Jika program menangkap eksepsi di dalam salah satu blok catch yang disediakan, maka program akan memproses eksepsi,
kemudian blok finally akan
melepaskan semua sumberdaya yang dipakai dan kendali program berlanjut untuk
mengeksekusi statemen pertama setelah blok finally.
Jika program tidak menangkap eksepsi yang terjadi, blok finally juga masih tetap membebaskan sumberdaya yang dipakai dan
eksepsi akan dicoba untuk ditangkap dalam metode pemanggil.
Jika suatu eksepsi, yang terjadi di dalam
suatu blok try, tidak dapat
ditangkap oleh salah satu dari blok catch,
maka program akan melompati sisa blok try
dan kendali program akan mengeksekusi blok finally.
Kemudian program akan melewatkan eksepsi tersebut kepada blok try sebelah luar, yang biasanya berada
di dalam metode pamanggil, dimana blok catch
terkait bisa menangkapnya. Hal ini dapat terjadi pada banyak level blok try.
Jika suatu blok catch menangkap suatu eksepsi, blok finally masih tetap dieksekusi. Kemudian eksepsi tersebut
dilewatkan kepada blok try sebelah
luar, yang biasanya ditempatkan di dalam metode pemanggil.
Gambar 2.3 mendemonstrasikan bahwa blok finally tetap dieksekusi meskipun bila
eksepsi tidak dilemparkan di dalam blok try.
Program memuat metode Main (baris
8-47) dan empat metode lain yang dipanggil Main
untuk mendemonstrasikan finally.
Keempat metode tersebut adalah TidakLemparEksepsi
(baris 50-67), LemparEksepsiDenganCatch
(baris 70-89), LemparEksepsiTanpaCatch
(baris 92-108), dan LemparEksepsiCatchLemparUlang
(baris 111-136).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
// Gambar. 2.3: MenggunakanEksepsi.cs
// menggunakan blok-blok finally.
// blok-blok
finally selalu dieksekusi, meski jika tidak ada eksepsi yang terjadi.
using System;
class
MenggunakanEksepsi
{
static void Main()
{
// Kasus 1: Tidak ada eksepsi yang terjadi pada metode terpanggil
Console.WriteLine( "Memanggil
TidakLemparEksepsi" );
TidakLemparEksepsi();
// Kasus 2: Eksepsi terjadi dan ditangkap pada metode terpanggil
Console.WriteLine( "\nMemanggil
LemparEksepsiDenganCatch" );
LemparEksepsiDenganCatch();
// Kasus 3: Eksepsi terjadi, tetapi tidak
ditangka pada metode terpanggil
// karena tidak ada blok catch.
Console.WriteLine( "\nMemanggil
LemparEksepsiTanpaCatch" );
// memanggil LemparEksepsiTanpaCatch
try
{
LemparEksepsiTanpaCatch();
} // akhir try
catch
{
Console.WriteLine( "Menangkap eksepsi dari " +
"LemparEksepsiTanpaCatch di dalam Main" );
} // akhir catch
// Kasus 4: Eksepsi terjadi dan ditangkap pada metode terpanggil,
// kemudian dilempar-ulang kepada pemanggil.
Console.WriteLine( "\nMemanggil
LemparEksepsiCatchLemparUlang" );
// memanggil LemparEksepsiCatchLemparUlang
try
{
LemparEksepsiCatchLemparUlang();
} // akhir try
catch
{
Console.WriteLine( "Menangkap eksepsi dari " +
"LemparEksepsiCatchLemparUlang di dalam Main" );
} // akhir catch
} // akhir metode Main
// tidak ada eksepsi yang dilempar
static void TidakLemparEksepsi()
{
// blok try tidak melempar eksepsi
try
{
Console.WriteLine("Di dalam TidakLemparEksepsi");
} // akhir try
catch
{
Console.WriteLine( "Blok catch ini tidak pernah dieksekusi"
);
} // akhir catch
finally
{
Console.WriteLine("finally dieksekusi di
dalam TidakLemparEksepsi");
} // akhir
finally
Console.WriteLine("Akhir
dari TidakLemparEksepsi");
} // akhir metode TidakLemparEksepsi
// melempar eksepsi dan menangkapnya secara lokal
static void LemparEksepsiDenganCatch()
{
// blok try melempar eksepsi
try
{
Console.WriteLine("Di dalam LemparEksepsiDenganCatch");
throw
new
Exception("Eksepsi di dalam
LemparEksepsiDenganCatch");
} // akhir try
catch ( Exception
parameterEksepsi )
{
Console.WriteLine( "Pesan: " +
parameterEksepsi.Message );
} // akhir catch
finally
{
Console.WriteLine(
"finally dieksekusi di dalam LemparEksepsiDenganCatch");
} // akhir
finally
Console.WriteLine("Akhir
dari LemparEksepsiDenganCatch");
} // akhir metode LemparEksepsiDenganCatch
// melempar eksepsi dan tidak menangkapnya secara lokal
static void LemparEksepsiTanpaCatch()
{
// melempar eksepsi, tetapi tidak menangkapnya
try
{
Console.WriteLine("Di dalam LemparEksepsiTanpaCatch");
throw new Exception("Eksepsi di dalam LemparEksepsiTanpaCatch");
} // akhir try
finally
{
Console.WriteLine( "finally dieksekusi di dalam " +
"LemparEksepsiTanpaCatch");
} // akhir
finally
// kode tidak dieksekusi; error logika
Console.WriteLine("Akhir
dari LemparEksepsiTanpaCatch");
} // akhir metode LemparEksepsiTanpaCatch
// melempar eksepsi, menangkapnya dan melemparnya ulang
static void LemparEksepsiCatchLemparUlang()
{
// blok try melempar eksepsi
try
{
Console.WriteLine("Di dalam LemparEksepsiCatchLemparUlang");
throw new Exception("Eksepsi di dalam
LemparEksepsiCatchLemparUlang");
} // akhir try
catch ( Exception
parameterEksepsi )
{
Console.WriteLine( "Pesan: " +
parameterEksepsi.Message );
// melempar-ulang eksepsi untuk
pemrosesan lebih lanjut
throw;
// kode tidak dieksekusi; error
logika
} // akhir catch
finally
{
Console.WriteLine( "finally dieksekusi di dalam " +
"LemparEksepsiCatchLemparUlang");
} // akhir
finally
// sembarang kode yang ditempatkan di sini tidak akan pernah
dieksekusi
Console.WriteLine("Akhir
dari LemparEksepsiCatchLemparUlang");
} // akhir metode LemparEksepsiCatchLemparUlang
} // akhir kelas MenggunakanEksepsi
|
Memanggil TidakLemparEksepsi
Di dalam TidakLemparEksepsi
finally dieksekusi di dalam TidakLemparEksepsi
Akhir dari TidakLemparEksepsi
Memanggil LemparEksepsiDenganCatch
Di dalam LemparEksepsiDenganCatch
Pesan: Eksepsi di dalam LemparEksepsiDenganCatch
finally dieksekusi di dalam LemparEksepsiDenganCatch
Akhir dari LemparEksepsiDenganCatch
Memanggil LemparEksepsiTanpaCatch
Di dalam LemparEksepsiTanpaCatch
finally dieksekusi di dalam LemparEksepsiTanpaCatch
Menangkap eksepsi dari LemparEksepsiTanpaCatch di
dalam Main
Memanggil LemparEksepsiCatchLemparUlang
Di dalam LemparEksepsiCatchLemparUlang
Pesan: Eksepsi di dalam
LemparEksepsiCatchLemparUlang
finally dieksekusi di dalam
LemparEksepsiCatchLemparUlang
Menangkap eksepsi dari LemparEksepsiCatchLemparUlang
di dalam Main
|
Baris 12 pada Main memanggil metode TidakLemparEksepsi.
Blok try pada metode ini menampilkan
sebuah pesan (baris 55). Karena blok try
tersebut tidak melempar sembarang eksepsi, maka kendali program akan
mengabaikan blok catch (baris 57-60)
dan mengekseksi blok finally (baris
61-64), yang menampilkan sebuah pesan. Pada titik ini, kendali program
berlanjut ke statemen pertama yang berada setelah kurung kurawal penutup pada
blok finally (baris 66), yang
menampilkan sebuah pesan untuk mengindikasikan bahwa akhir metode telah diraih.
Kemudian, kendali program kembali ke Main.
Melempar Eksepsi Menggunakan Statemen throw
Baris 16 pada Main memanggil metode LemparEksepsiDenganCatch
(baris 70-89), yang diawali dengan blok try
(baris 73-77) dengan menampilkan sebuah pesan. Selanjutnya, blok try tersebut menciptakan sebuah objek Exception dan menggunakan statemen throw untuk melemparkannya (baris 76).
Pengeksekusian statemen throw
mengindikasikan bahwa ada masalah yang terjadi pada kode. Statemen throw menetapkan sebuah objek untuk
dilemparkan. Operand dari statemen throw
dapat bertipe Exception atau
sembarang tipe yang diderivasi dari kelas Exception.
String yang dilewatkan kepada
konstruktor menjadi pesan error dari objek eksepsi. Ketika statemen throw di dalam suatu blok try dieksekusi dan kendali program akan
langsung keluar dari blok try
tersebut dan berlanjut ke blok catch
pertama yang cocok (baris 78-81) yang berada setelah blok try itu. Pada contoh ini, tipe eksepsi (Exception) yang dilemparkan cocok dengan tipe yang dispesifikasi
pada catch, jadi baris 80
menampilkan sebuah pesan yang mengindikasikan eksepsi yang telah terjadi.
Kemudian, blok finally (baris 82-86)
dieksekusi dan menampilkan sebuah pesan. Pada titik ini, kendali program
berlanjut ke statemen pertama yang berada setelah kurung kurawal penutup pada
blok finally (baris 88), yang
menampilkan sebuah pesan untuk mengindikasikan bahwa akhir metode telah diraih.
Kendali program kemudian kembali ke Main.
Pada baris 80, Anda menggunakan properti Message
dari objek eksepsi untuk membaca pesan error yang berkaitan dengan eksepsi yang
terjadi (pesan tersebut dilewatkan kepada konstruktor Exception).
Baris 23-31 pada Main mendefinisikan suatu statemen try, dimana di dalamnya Main
memanggil metode LemparEksepsiTanpaCatch
(baris 92-108). Blok try tersebut
memampukan Main untuk menangkap
sembarang eksepsi yang dilemparkan oleh LemparEksepsiTanpaCatch.
Blok try pada baris 95-99 pada LemparEksepsiTanpaCatch dimulai dengan
menampilkan sebuah pesan. Selanjutnya, blok try itu melemparkan sebuah Exception
(baris 98).
Normalnya, kendali program akan
berlanjut ke blok catch pertama yang
berada setelah blok try. Namun, blok
try ini tidak memiliki blok catch. Oleh karena itu, eksepsi tidak
ditangkap di dalam metode LemparEksepsiTanpaCatch.
Kendali program berlanjut ke blok finally
(baris 100-104), yang menampilkan sebuah pesan. Pada titik ini, kendali program
kembali ke Main. Jadi, sembarang
statemen yang berada setelah blok try
(misalnya, baris 107) tidak akan pernah dieksekusi. Pada contoh ini, statemen
semacam itu menyebabkan error logika, karena eksepsi yang dilempar pada baris
98 tidak ditangkap. Pada Main, blok catch pada baris 27-31 menangkap
eksepsi dan menampilkan sebuah pesan yang mengindikasikan bahwa eksepsi telah
terjadi pada Main.
Melemparkan-Ulang Eksepsi
Baris 38-46 pada Main mendefinisikan sebuah statemen try dimana di dalamnya Main
memanggil metode LemparEksepsiCatchLemparUlang
(baris 111-136). Statemen try
memampukan Main untuk menangkap
sembarang eksepsi yang dilemparkan oleh LemparEksepsiCatch-LemparUlang.
Statemen try pada baris 114-132 pada
LemparEksepsiCatchLemparUlang
dimulai dengan menampilkan sebuah pesan. Selanjutnya, blok try melemparkan sebuah Exception
(baris 117). Kendali program langsung keluar dari blok try tersebut dan berlanjut ke blok catch pertama (baris 119-127) yang berada setelah blok try itu. Pada contoh ini, tipe yang
dilemparkan (Exception) cocok dengan tipe yang dispesifikasi pada catch, jadi baris 121 menampilkan
sebuah pesan yang mengindikasikan di mana eksepsi terjadi. Baris 124
menggunakan statemen throw untuk
melempar-ulang eksepsi. Ini mengindikasikan bahwa blok try melakukan pemrosesan parsial terhadap eksepsi dan sekarang
melempar-ulang eksepsi tersebut (pada kasus ini, kembali ke metode Main) untuk pemrosesan berikutnya.
Penanganan eksepsi pada metode LemparEksepsiCatchLemparUlang tidak
sempurna, karena statemen throw pada
baris 124 secara mendadak menghentikan blok catch. Jika terdapat sembarang kode yang berada di antara baris 124
dan kurung kurawal penutup blok catch
itu, maka kode tersebut tidak akan dieksekusi. Ketika baris 124 dieksekusi,
metode LemparEksepsiCatch-LemparUlang
akan berhenti dan mengembalikan kendali program kepada Main. Sekali lagi, blok finally
(baris 128-132) dieksekusi dan menampilkan sebuah pesan sebelum kendali program
kembali kepada Main. Ketika kendali
kembali kepada Main, blok catch pada baris 42-46 akan menangkap
eksepsi dan menampilkan sebuah pesan yang mengindikasikan bahwa eksepsi telah
ditangkap. Kemudian program berhenti.
Setelah Blok finally
Statemen selanjutnya yang akan
dieksekusi setelah blok finally
berhenti bergantung dari keadaan penanganan eksepsi. Jika blok try dengan sukses dieksekusi, atau jika
blok catch menangkap dan menangani
eksepsi, maka program akan berlanjut mengeksekusi statemen berikutnya yang
berada setelah blok finally. Namun,
jika eksepsi tidak ditangkap, atau jika blok catch melempar-ulang eksepsi, maka kendali program akan berlanjut
ke kurung kurawal penutup dari blok try
berikutnya. Kurung kurawal penutup blok try
dapat berada di metode pemanggil atau di dalam salah satu pemanggilnya. Adalah
memungkinkan untuk membuat sebuah statemen try
bersarang di dalam suatu blok try.
Pada kasus semacam itu, blok catch
dari statemen try sebelah luar akan
memproses sembarang eksepsi yang tidak ditangkap pada statemen try sebelah dalam. Jika sebuah blok try dieksekusi dan memiliki suatu blok finally, maka blok finally itu tetap dieksekusi bahkan jika blok try berhenti secara mendadak karena keberadaan statemen return.
2.5
Properti-Properti pada Kelas Exception
Semua tipe eksepsi diderivasi dari
kelas Exception, yang memiliki
beberapa properti. Properti-properti tersebut digunakan untuk memformulasikan
pesan yang menjelaskan eksepsi yang ditangkap. Dua properti penting adalah Message dan StackTrace. Properti Message
menyimpan pesan error yang berkaitan dengan sebuah objek Exception. Pesan ini dapat berupa pesan default yang berkaitan
dengan tipe eksepsi atau pesan termodifikasi yang dilewatkan kepada konstruktor
dari objek Exception ketika objek Exception dilemparkan. Properti StackTrace memuat suatu string yang
merepresentasikan tumpukan pemanggilan-metode. Properti StackTrace merepresentasikan serangkaian metode yang belum selesai
diproses pada saat eksepsi terjadi.
Properti InnerException
Properti lain yang sering digunakan
oleh programer pustaka-kelas adalah InnerException. Umumnya, para programer
kelas pustaka “membungkus” objek-objek eksepsi yang ditangkap pada kodenya
sehingga kemudian dapat melempar tipe eksepsi baru yang spesifik dengan pustaka
yang diciptakan programer. Sebagai contoh, seorang programer yang
mengimplementasikan sistem akunting memiliki kode pemrosesan akun dimana di
dalamnya angka-angka akun dientrikan sebagai string tetapi direpresentasikan sebagai int pada kode. Ingat bahwa sebuah program dapat mengkonversi string menjadi int menggunakan Convert.ToInt32,
yang melemparkan sebuah ekspesi FormatException
ketika ia menjupai format angka tak-valid.
Ketika sebuah format tak-valid
dijumpai, programer sistem-akunting akan menggunakan pesan error yang berbeda
dari pesan default yang disediakan oleh FormatException
atau akan menciptakan sebuah tipe eksepsi baru, seperti FormatAngkaTakValidException. Pada kasus itu, Anda perlu
menyediakan kode untuk menangkap FormatException,
kemudian menciptakan sebuah tipe baru yang cocok dengan tipe Exception pada blok catch dan melewatkan eksepsi asli
sebagai salah satu argumen konstruktor. Objek eksepsi asli menjadi InnerException dari objek eksepsi yang
baru. Ketika eksepsi FormatAngkaTakValidException
terjadi pada kode yang menggunakan pustak sistem akunting, blok catch yang menangkap eksepsi tersebut
dapat memperoleh referensi yang menunjuk ke eksepsi asli melalui properti InnerException. Jika properti InnerException bernilai null, maka ini mengindikasikan bahwa
eksepsi tidak disebabkan oleh eksepsi lain.
Properti-Properti Exception Lain
Kelas Exception menyediakan properti-properti lain, seperti HelpLink, Source, dan TargetSite.
Properti HelpLink menetapkan lokasi
dari file help yang menjelaskan
masalah yang terjadi. Properti ini bernilai null jika file tersebut tidak ada. Properti Source menetapkan nama aplikasi atau objek yang menyebabkan
eksepsi. Properti TargetSite
menetapkan metode dimana eksepsi berawal.
Mendemonstrasikan Properti-Properti Exception
Contoh selanjutnya (Gambar 2.4)
mendemonstrasikan properti Message, StackTrace, dan InnerException dari kelas Exception.
Selain itu, contoh ini juga mengintroduksi penguraian tumpukan, dimana sebuah
eksepsi dilemparkan tetapi tidak ditangkap oleh skop tertentu. Hal ini
menyebabkan tumpukan pemanggilan-metode terurai. Contoh ini menjejak
metode-metode pada tumpukan pemanggilan menggunakan properti StackTrace.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
// Gambar 2.4: Properti.cs
// Penguraian tumpukan dan
properti-properti kelas Exception .
// Mendemonstrasikan penggunaan
properti Message, StackTrace dan InnerException.
using System;
class Properti
{
static void Main()
{
// memanggil Metode1; setiap Exception yang dibangkitkan ditangkap
// di dalam blok catch yang mengikutinya
try
{
Metode1();
} // akhir try
catch ( Exception
parameterEksepsi )
{
// menampilkan
representasi string dari Exception, kemudian menampilkan
// properti-proprti Message,
StackTrace dan InnerException
Console.WriteLine("parameterEksepsi.ToString: \n{0}\n",
parameterEksepsi );
Console.WriteLine("parameterEksepsi.Message:
\n{0}\n",
parameterEksepsi.Message );
Console.WriteLine("parameterEksepsi.StackTrace:
\n{0}\n",
parameterEksepsi.StackTrace
);
Console.WriteLine("parameterEksepsi.InnerException:
\n{0}\n",
parameterEksepsi.InnerException
);
} // akhir catch
} // akhir metode Main
// memanggil Metode2
static void Metode1()
{
Metode2();
} // akhir metode Metode1
// memanggil Metode3
static void Metode2()
{
Metode3();
} // akhir metode Metode2
// melemparkan sebuah Exception yang memuat sebuah InnerException
static void Metode3()
{
// mencoba mengkonversi string menjadi int
try
{
Convert.ToInt32( "Bukan sebuah integer" );
} // akhir try
catch ( FormatException
parameterEksepsiFormat )
{
// membungkus FormatException di
dalam Exception baru
throw new Exception( "Exception
terjadi pada Metode3",
parameterEksepsiFormat );
} // akhir catch
} // akhir metode Metode3
} // akhir kelas
Properti
|
parameterEksepsi.ToString:
System.Exception: Exception terjadi pada Metode3
--->
System.FormatException:
Input
string was not in a correct format.
at
System.Number.StringToNumber(String str, NumberStyles options,
NumberBuffer&
number, NumberFormatInfo info, Boolean parseDecimal)
at
System.Number.ParseInt32(String s, NumberStyles style,
NumberFormatInfo
info)
at
System.Convert.ToInt32(String value)
at
Properti.Metode3() in e:\Projects Visual C#\Properti\
Properti\Properti.cs:line 49
--- End of
inner exception stack trace ---
at
Properti.Metode3() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 54
at
Properti.Metode2() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 40
at
Properti.Metode1() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 34
at
Properti.Main() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 14
parameterEksepsi.Message:
Exception terjadi pada Metode3
parameterEksepsi.StackTrace:
at
Properti.Metode3() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 54
at
Properti.Metode2() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 40
at
Properti.Metode1() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 34
at
Properti.Main() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 14
parameterEksepsi.InnerException:
System.FormatException: Input string was not in a correct
format.
at
System.Number.StringToNumber(String str, NumberStyles options,
NumberBuffer&
number, NumberFormatInfo info, Boolean parseDecimal)
at
System.Number.ParseInt32(String s, NumberStyles style,
NumberFormatInfo
info)
at
System.Convert.ToInt32(String value)
at
Properti.Metode3() in e:\Projects Visual C#\Properti\Properti\
Properti.cs:line 49
|
Eksekusi program diawali dari Main, yang menjadi metode pertama pada
tumpukan pemanggilan metode. Baris 14 pada blok try di dalam main memanggil Metode1
(dideklarasikan pada baris 32-35), yang menjadi metode kedua pada tumpukan.
Jika Metode1 melemparkan sebuah
eksepsi, maka blok catch pada baris
16-28 akan menangani eksepsi itu dan menampilkan informasi seputar eksepsi yang
terjadi. Baris 34 pada Metode1
memanggil Metode2 (baris 38-41),
yang menjadi metode ketiga pada tumpukan. Kemudian baris 40 pada Metode2 memanggil Metode3 (baris 44-57), yang menjadi metode keempat pada tumpukan.
Pada titik ini, tumpukan
pemanggilan-metode (dari atas ke bawah) untuk program adalah:
Metode3
Metode2
Metode1
Main
Metode yang dipanggil paling belakangan
(Metode3) berada di atas tumpukan;
metode pertama yang dipanggil (Main)
berada di bawah tumpukan. Statemen try
(baris 47-56) pada Metode3 memanggil
metode Convert.ToInt32 (baris 49),
yang mencoba mengkonversi string
menjadi int. Pada titik ini, Convert.ToInt32 menjadi metode kelima
dan terakhir pada tumpukan pemanggilan.
Melempar Exception dengan InnerException
Karena argumen pada Convert.ToInt32 tidak dalam format int, baris 49 melemparkan sebuah
eksepsi FormatException yang
ditangkap pada baris 52 pada Metode3.
Eksepsi tersebut menghentikan pemanggilan terhadap Convert.ToInt32, jadi metode tersebut dihapus dari tumpukan
pemanggilan-metode. Blok catch pada Metode3 kemudian menciptakan dan
melemparkan sebuah objek Exception.
Argumen pertama pada konstruktor Exception
adalah pesan error yang dimodifikasi “Exception
terjadi pada Metode3”. Argumen keduanya adalah InnerException, yaitu eksepsi FormatException
yang ditangkap. Properti StackTrace
untuk objek eksepsi yang baru ini merefleksikan titik dimana eksepsi dilemparkan
(baris 54-55). Sekarang Metode3
berhenti, karena eksepsi yang dilemparkan di dalam blok catch tidak ditangkap di dalam tubuh metode itu. Jadi, kendali
program kembali ke statemen yang memanggil Metode3
(yaitu Metode2). Ini akan menghapus
atau mengurai Metode3 dari tumpukan
pemanggilan-metode.
Ketika kendali program kembali ke baris
40 pada Metode2, kompiler menentukan
bahwa baris 40 tidak berada di dalam sebuah blok try. Oleh karena itu, eksepsi tidak ditangkap di dalam Metode2, dan Metode2 pun berhenti. Ini akan menghapus Metode2 dari tumpukan pemanggilan dan mengembalikan kendali program
kepada baris 34 pada Metode1.
Di sini lagi, baris 34 tidak berada di
dalam sebuah blok try, jadi Metode1 tidak dapat menangkap eksepsi.
Metode ini berhenti dan dihapus dari tumpukan pemanggilan, kemudian
mengembalikan kendali ke baris 14 pada Main,
yang berlokasi di dalam suatu blok try.
Blok try pada Main berhenti dan blok catch
(baris 16-28) menangkap eksepsi. Blok catch
menggunakan properti Message, StackTract, dan InnerException untuk menghasilkan keluaran. Penguraian tumpukan
berlanjut sampai sebuah blok catch
menangkap eksepsi atau sampai program berhenti.
Menampilkan Informasi Seputar Exception
Blok keluaran pertama pada Gambar 2.4
memuat representasi string atas
eksepsi, yang merupakan nilai balik dari pemanggilan implisit terhadap metode ToString. Representasi string diawali dengan nama kelas
eksepsi yang diikuti dengan nilai properti Message.
Empat item berikutnya menyajikan jejak tumpukan dari objek InnerException. Informasi lain pada blok ini menunjukkan StackTrace untuk eksepsi yang
dilemparkan di dalam Metode3.
Properti StackTrace
merepresentasikan keadaan dari tumpukan pemanggilan-metode pada titik lempar
eksepsi, bukan pada titik dimana eksepsi akhirnya ditangkap. Setiap baris StackTrace yang diawali dengan “at” merepresentasikan sebuah metode
pada tumpukan pemanggilan. Tiap baris ini mengindikasikan metode dimana di
dalamnya eksepsi terjadi, file dimana di dalamnya metode ditempatkan, dan nomor
baris dari titik lempar pada file. Informasi seputar InnerException mencakup jejak tumpukan inner-exception.
Blok keluaran berikutnya (dua baris)
menampilkan nilai properti Message (Exception terjadi pada Metode3) dari
eksepsi yang dilempar pada Metode3.
Blok ketiga pada keluaran menampilkan
properti StackTrace dari eksepsi
yang dilempar pada Metode3. Properti
StackTrace ini memuat jejak tumpukan
diawali dari baris 54 pada Metode3,
karena di situlah titik di mana objek Exception
diciptakan dan dilemparkan. Jejak tumpukan selalu diawali dari titik lempar
eksepsi.
Terakhir, blok keluaran terakhir
menampilkan representasi string atas properti InnerException, yang mencantumkan namespace dan nama kelas dari objek eksepsi, berikut dengan
properti Message dan StackTracenya.
2.6
Kelas Eksepsi Buatan Sendiri
Dalam banyak kasus, Anda dapat
menggunakan kelas-kelas eksepsi dari .NET Framework
Class Library untuk mengindikasikan eksepsi-eksepsi yang terjadi pada
program Anda. Pada beberapa kasus, Anda mungkin ingin menciptakan kelas eksepsi
sendiri yang spesifik dengan permasalahan pada program Anda. Kelas eksepsi
terdefinisi-pengguna harus diderivasi secara langsung atau tak-langsung dari
kelas Exception pada namespace System. Ketika Anda menuliskan kode
yang melemparkan eksepsi semacam itu, Anda perlu mendokumentasikannya, sehingga
pengembang lain yang menggunakan kode Anda akan mengetahui bagaimana
menanganinya.
Kelas AngkaNegatifException
Gambar 2.5 – 2.6 mendemonstrasikan
sebuah kelas eksepsi buatan sendiri. Kelas AngkaNegatifException
(Gambar 2.5) merepresentasikan eksepsi yang terjadi ketika sebuah program
melakukan suatu operasi ilegal pada angka negatif, seperti mencoba untuk
menghitung akar kuadratnya.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//
Gambar 2.5: AngkaNegatifException.cs
// AngkaNegatifException merepresentasikan
eksepsi-eksepsi yang disebabkan oleh
//
operasi-operasi ilegal terhadap angka-angka negatif.
using
System;
class
AngkaNegatifException : Exception
{
// konstruktor default
public AngkaNegatifException()
: base( "Operasi ilegal untuk sebuang angka negatif" )
{
// tubuh
kosong
} // akhir konstruktor default
// konstruktor untuk memodifikasi pesan error
public AngkaNegatifException( string
nilaiPesan )
: base( nilaiPesan )
{
// tubuh
kosong
} // akhir konstruktor satu-argumen
// konstruktor untuk memodifikasi pesan error
// dan menetapkan objek InnerException
public AngkaNegatifException(string
nilaiPesan,
Exception inner )
: base(nilaiPesan, inner)
{
// tubuh
kosong
} // akhir konstruktor dua-argumen
} // akhir kelas AngkaNegatifException
|
Sesuai dengan dokumentasi Microsoft,
eksepsi terdefinisi-pengguna harus mewarisi kelas Exception, memiliki nama kelas yang diakhiri dengan “Exception”, dan mendefinisikan tiga
konstruktor: sebuah konstruktor tanpa parameter; sebuah konstruktor yang
menerima sebuah argumen string
(pesan error); dan sebuah konstruktor yang menerima sebuah argumen string dan sebuah argumen Exception (pesan error dan objek inner-exception). Pendefinisian ketiga konstruktor ini membuat kelas
eksepsi Anda lebih fleksibel, yang memampukan programer lain agar lebih mudah
menggunakan dan mewarisinya.
Karena AngkaNegatifException sering terjadi pada saat operasi aritmatika,
jadi logis bila Angka-NegatifException
mewarisi kelas ArithmeticException.
Namun, kelas ArithmeticException
mewarisi kelas SystemException.
Tetapi, menurut Microsoft, yang terbaik dilakukan adalah mewarisi dari Exception, bukan dari SystemException. Pada kasus ini, Anda
bisa saja menggunakan kelas ArgumentException
(tersedia pada .NET Framework), yang
direkomendasi untuk nilai-nilai argumen tak-valid. Anda menciptakan tipe
eksepsi sendiri di sini hanya untuk tujuan demonstrasi saja.
Kelas UjiAkarKuadrat
Kelas UjiAkarKuadrat (Gambar 2.6) mendemonstrasikan kelas eksepsi yang
telah dibuat. Aplikasi memampukan pengguna untuk memasukkan sebuah angka
numerik, kemudian memanggil metode AkarKuadrat
(baris 40-48) untuk menghitung akar kuadrat dari nilai itu. Untuk melakukan
perhitungan ini, AkarKuadrat
memanggil metode Sqrt dari kelas Math, yang menerima sebuah nilai double sebagai argumennya. Normalnya,
jika argumennya negatif, maka metode Sqrt
akan menghasilkan NaN. Pada program
ini, Anda akan mencegah pengguna untuk menghitung akar kuadrat atas suatu nilai
negatif. Jika nilai numerik yang dimasukkan pengguna bernilai negatif, maka
metode AkarKuadrat akan melemparkan
eksepsi AngkaNegatifException (baris
44-45). Sebaliknya, AkarKuadrat
memanggil metode Sqrt dari kelas Math untuk menghitung akar kuadrat
(baris 47).
Ketika pengguna memasukkan sebuah
nilai, statemen try (baris 14-34)
mencoba memanggil AkarKuadrat
menggunakan nilai masukan oleh pengguna. Jika masukan pengguna bukan suatu
angka, maka eksepsi FormatException
akan terjadi, dan blok catch pada
baris 25-29 akan memproses eksepsi itu. Jika pengguna memasukkan sebuah angka
negatif, maka metode AkarKuadrat
akan melemparkan AngkaNegatifException
(baris 44-45); blok catch pada baris
30-34 menangkap dan menangani tipe eksepsi ini.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
//
Gambar 2.6: UjiAkarKuadrat.cs
//
Mendemonstrasikan sebuah kelas eksepsi terdefinisi-pengguna.
using
System;
class
UjiAkarKuadrat
{
static
void Main( string[] args )
{
bool
loopLanjut = true;
do
{
// menangkap sembarang
AngkaNegatifException yang dilempar
try
{
Console.Write(
"Masukkan sebuah nilai untuk
menghitung akar kuadratnya: " );
double nilaiMasukan = Convert.ToDouble( Console.ReadLine() );
double hasil = AkarKuadrat( nilaiMasukan );
Console.WriteLine( "Akar kuadrat dari {0} adalah
{1:F6}\n",
nilaiMasukan, hasil );
loopLanjut = false;
} // akhir try
catch ( FormatException eksepsiFormat )
{
Console.WriteLine( "\n"
+ eksepsiFormat.Message );
Console.WriteLine( "Silahkan masukkan sebuah nilai double.\n" );
} // akhir catch
catch ( AngkaNegatifException angkaNegatifException )
{
Console.WriteLine(
"\n" + angkaNegatifException.Message );
Console.WriteLine( "Silahkan masukkan sebuah nilai
tak-negatif.\n" );
} // akhir catch
} while ( loopLanjut );
} // akhir Main
// menghitung akar kuadrat dari
parameter; melemparkan
// AngkaNegatifException jika parameter
bernilai negatif
public
static double AkarKuadrat( double
nilai )
{
// jika operand negatif, lemparkan
AngkaNegatifException
if
( nilai < 0 )
throw new
AngkaNegatifException(
"Akar kuadrat dari angka negatif tidak diijinkan" );
else
return Math.Sqrt( nilai ); // menghitung akar kuadrat
} // akhir metode AkarKuadrat
} // akhir kelas UjiAkarKuadrat
|
Masukkan sebuah nilai
untuk menghitung akar kuadratnya: 30
Akar kuadrat dari 30
adalah 5.477226
|
Masukkan sebuah nilai
untuk menghitung akar kuadratnya: jogja
Input string was not in
a correct format.
Silahkan masukkan
sebuah nilai double.
Masukkan sebuah nilai
untuk menghitung akar kuadratnya: 25
Akar kuadrat dari 25
adalah 5.000000
|
Masukkan sebuah nilai
untuk menghitung akar kuadratnya: -2
Akar kuadrat dari angka
negatif tidak diijinkan
Silahkan masukkan
sebuah nilai tak-negatif.
Masukkan sebuah nilai
untuk menghitung akar kuadratnya: 2
Akar kuadrat dari 2
adalah 1.414214
|
No comments:
Post a Comment