- Derleme hatasını çalışma zamanı istisnasından ayırt etmek
- İstisnaları
try, birden fazlacatchbloğu vefinallyile yakalamak throwile istisna fırlatmak ve kendi istisna sınıfını oluşturmak- Beklenen hatalar için
TryParsegibi yolları seçmek
Derleyici birçok hatayı program başlamadan önce bulur ama hepsini değil. Kullanıcı yaş yerine “abc” yazar, bir dosya silinmiştir, internet kesilir, biri sıfıra böler... Bu sorunlar ancak program çalışırken ortaya çıkar. C#'ta böyle durumlarda bir istisna (exception) oluşur. Onu yakalamazsan program “Unhandled exception” mesajıyla durur; yakalarsan kullanıcıya sorunu anlaşılır biçimde açıklayıp işe devam edebilirsin.
try ve catch
Hata verebilecek kod bir try bloğuna yazılır. Bir istisna oluştuğu anda try bloğunun kalan satırları atlanır ve kontrol uygun catch bloğuna geçer. Her catch belirli bir istisna türünü yakalar; bu yüzden farklı hatalara farklı tepkiler verilebilir.
string[] inputs = ["42", "abc", "99999999999"];
foreach (string input in inputs)
{
try
{
int number = int.Parse(input);
Console.WriteLine($"OK: {number}");
}
catch (FormatException)
{
Console.WriteLine($"'{input}' is not a number");
}
catch (OverflowException)
{
Console.WriteLine($"'{input}' is too big for int");
}
}OK: 42 'abc' is not a number '99999999999' is too big for int
İstisna aynı zamanda bir nesnedir: catch (IndexOutOfRangeException ex) yazıldığında ex değişkeni onun bilgilerini tutar, örneğin açıklama metni olan ex.Message. Tüm istisnalar Exception sınıfından türer; bu yüzden catch (Exception ex) her hatayı yakalar, onu her zaman en sona yaz. finally bloğu ise hata olsa da olmasa da her zaman çalışır: bir dosyayı kapatmak ya da bir kaynağı serbest bırakmak için uygundur.
int[] scores = [90, 75, 88];
try
{
Console.WriteLine(scores[5]);
}
catch (IndexOutOfRangeException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
Console.WriteLine("This line always runs.");
}
try
{
int zero = 0;
Console.WriteLine(10 / zero);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.GetType().Name}: {ex.Message}");
}Error: Index was outside the bounds of the array. This line always runs. DivideByZeroException: Attempted to divide by zero.
| İstisna | Ne zaman oluşur |
|---|---|
FormatException | int.Parse("abc") — metin bir sayı değil |
DivideByZeroException | bir tam sayı sıfıra bölünüyor |
IndexOutOfRangeException | dizide olmayan bir indeks |
KeyNotFoundException | sözlükte olmayan bir anahtar |
NullReferenceException | null olan bir değişkenin üyesine erişim |
FileNotFoundException | açılmak istenen dosya yok |
throw: istisnayı kendin fırlatmak
Bir metot işini doğru yapamıyorsa sessizce yanlış bir sonuç döndürmek yerine throw ile bir istisna fırlatmalıdır. Hazır türler çoktur: hatalı argüman için ArgumentException, nesnenin o anki durumunda izin verilmeyen bir işlem için InvalidOperationException. Gerekirse Exception'dan türeyen kendi istisna sınıfını oluşturabilirsin; bu, önceki dersteki kalıtımın gerçek bir uygulamasıdır.
var wallet = new Wallet(100);
try
{
wallet.Pay(30);
wallet.Pay(250);
wallet.Pay(10);
}
catch (NotEnoughMoneyException ex)
{
Console.WriteLine($"Payment failed: {ex.Message}");
}
Console.WriteLine($"Left: {wallet.Balance} AZN");
class NotEnoughMoneyException(string message) : Exception(message);
class Wallet(decimal balance)
{
public decimal Balance { get; private set; } = balance;
public void Pay(decimal amount)
{
if (amount > Balance)
throw new NotEnoughMoneyException($"need {amount} AZN, have {Balance} AZN");
Balance -= amount;
Console.WriteLine($"Paid {amount} AZN");
}
}Paid 30 AZN Payment failed: need 250 AZN, have 70 AZN Left: 70 AZN
wallet.Pay(10) hiç çalışmadı: bir istisnadan sonra try bloğunun geri kalanı atlanır.İstisnalar ne zaman kullanılmamalı
İstisnalar beklenmedik durumlar içindir. Kullanıcının yanlış bir şey yazması ise tamamen beklenen bir durumdur; bu yüzden metni kontrol etmek için try/catch yerine int.TryParse daha iyidir: kod daha kısadır, daha hızlı çalışır ve amacı açıkça gösterir. Aynı kural sözlükler için de geçerlidir: TryGetValue, anahtarın olmadığını hiç hata oluşturmadan kontrol eder.
string[] answers = ["15", "fifteen", "-3"];
foreach (string answer in answers)
{
if (!int.TryParse(answer, out int age))
Console.WriteLine($"'{answer}': please type digits");
else if (age is < 0 or > 120)
Console.WriteLine($"'{answer}': age must be 0-120");
else
Console.WriteLine($"Age accepted: {age}");
}Age accepted: 15 'fifteen': please type digits '-3': age must be 0-120
Önemli noktalar
- İstisna, program çalışırken oluşan bir hatadır; yakalanmazsa program durur.
trybloğunda istisna oluşunca kalan satırlar atlanır ve uyguncatchçalışır.- Özel
catchblokları önce,catch (Exception)en sonda yazılır;finallyher zaman çalışır. throw new ...Exception("...")hatalı bir durumu bildirir; kendi istisnalarınıException'dan türet.- Beklenen hatalar için
TryParseveTryGetValueistisnalardan daha iyidir.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
int.Parse("abc") hangi istisnayı fırlatır?