try-catch (C# Başvurusu)
try-catch deyimi, farklı özel durumlar için işleyicileri belirten bir veya daha fazla catch
yan tümcesinin ardından bir try
bloğundan oluşur.
Özel durum oluşturulduğunda, ortak dil çalışma zamanı (CLR) bu özel durumu işleyen deyimini arar catch
. Şu anda yürütülen yöntem böyle bir catch
blok içermiyorsa, CLR geçerli yöntemi çağıran yönteme bakar ve çağrı yığınını yukarı doğru kullanır. Hiçbir catch
blok bulunmazsa, CLR kullanıcıya işlenmeyen bir özel durum iletisi görüntüler ve programın yürütülmesini durdurur.
Blok, try
özel duruma neden olabilecek korunan kodu içerir. Blok, bir özel durum oluşturulana veya başarıyla tamamlanana kadar yürütülür. Örneğin, aşağıdaki bir null
nesneyi atama girişimi özel durumu tetikler NullReferenceException :
object o2 = null;
try
{
int i2 = (int)o2; // Error
}
Yan tümcesi herhangi bir özel durum türünü yakalamak için bağımsız değişkenler olmadan kullanılabilse catch
de, bu kullanım önerilmez. Genel olarak, yalnızca kurtarmayı bildiğiniz özel durumları yakalamanız gerekir. Bu nedenle, her zaman öğesinden System.Exceptiontüretilen bir nesne bağımsız değişkeni belirtmeniz gerekir. Özel durum işleyicinizin aslında çözümleyemediği özel durumların yanlış kabul edilmesinden kaçınmak için, özel durum türü mümkün olduğunca özel olmalıdır. Bu nedenle temel Exception
tür yerine somut özel durumları tercih edin. Örnek:
catch (InvalidCastException e)
{
// recover from exception
}
Aynı try-catch deyiminde birden fazla belirli catch
yan tümce kullanmak mümkündür. Bu durumda yan tümcelerin sırası catch
önemlidir çünkü catch
yan tümceler sırayla incelenir. Daha az belirli olanlardan önce daha belirli özel durumları yakalayın. Daha sonraki bir bloğa asla ulaşılamayacak şekilde catch bloklarınızı sipariş ederseniz derleyici bir hata üretir.
Bağımsız değişkenleri kullanmak catch
, işlemek istediğiniz özel durumları filtrelemenin bir yoludur. Ayrıca, özel durumun işlenip işlenmeyeceğine karar vermek için özel durumu daha ayrıntılı olarak inceleyen bir özel durum filtresi de kullanabilirsiniz. Özel durum filtresi false döndürürse, işleyici araması devam eder.
catch (ArgumentException e) when (e.ParamName == "…")
{
// recover from exception
}
Özel durum filtreleri, yığının zarar görmeden bırakılmasından dolayı yakalama ve yeniden oluşturma (aşağıda açıklanmıştır) için tercih edilir. Sonraki bir işleyici yığının dökümünü alırsa, özel durumun yalnızca yeniden yıkıldığı son yer yerine özgün olarak nereden geldiğini görebilirsiniz. Özel durum filtresi ifadelerinin yaygın bir kullanımı günlüğe kaydetmektir. Her zaman bir günlüğe çıkış veren false döndüren bir filtre oluşturabilirsiniz. Özel durumları işlemek zorunda kalmadan günlüğe kaydedebilir ve yeniden oluşturabilirsiniz.
Bir throw deyimi, deyimi tarafından yakalanan özel durumu yeniden oluşturmak için bir catch
blokta catch
kullanılabilir. Aşağıdaki örnek bir IOException özel durumdan kaynak bilgilerini ayıklar ve ardından özel durumu üst yönteme atar.
catch (FileNotFoundException e)
{
// FileNotFoundExceptions are handled here.
}
catch (IOException e)
{
// Extract some information from this exception, and then
// throw it to the parent method.
if (e.Source != null)
Console.WriteLine("IOException source: {0}", e.Source);
throw;
}
Bir özel durumu yakalayabilir ve farklı bir özel durum oluşturabilirsiniz. Bunu yaptığınızda, aşağıdaki örnekte gösterildiği gibi, iç özel durum olarak yakaladığınız özel durumu belirtin.
catch (InvalidCastException e)
{
// Perform some action here, and then throw a new exception.
throw new YourCustomException("Put your error message here.", e);
}
Aşağıdaki örnekte gösterildiği gibi, belirtilen bir koşul true olduğunda da bir özel durumu yeniden oluşturabilirsiniz.
catch (InvalidCastException e)
{
if (e.Data == null)
{
throw;
}
else
{
// Take some action.
}
}
Not
Genellikle daha temiz bir şekilde benzer bir sonuç elde etmek için bir özel durum filtresi kullanmak da mümkündür (ayrıca bu belgede daha önce açıklandığı gibi yığını değiştirmemek). Aşağıdaki örnekte, arayanlar için önceki örnekte olduğu gibi benzer bir davranış vardır. işlevi olduğunda e.Data
null
çağıranı geri atarInvalidCastException
.
catch (InvalidCastException e) when (e.Data != null)
{
// Take some action.
}
Bir try
bloğun içinden yalnızca burada bildirilen değişkenleri başlatın. Aksi takdirde, bloğun yürütülmesi tamamlanmadan önce bir özel durum oluşabilir. Örneğin, aşağıdaki kod örneğinde değişkeni n
bloğunun try
içinde başlatılır. Deyimindeki Write(n)
bloğun try
dışında bu değişkeni kullanma girişimi bir derleyici hatası oluşturur.
static void Main()
{
int n;
try
{
// Do not initialize this variable here.
n = 123;
}
catch
{
}
// Error: Use of unassigned local variable 'n'.
Console.Write(n);
}
Yakalama hakkında daha fazla bilgi için bkz. try-catch-finally.
Zaman uyumsuz yöntemlerdeki özel durumlar
Zaman uyumsuz yöntem bir zaman uyumsuz değiştirici tarafından işaretlenir ve genellikle bir veya daha fazla await ifadesi veya deyimi içerir. Await ifadesi , await işlecini veya TaskTask<TResult>öğesine uygular.
Denetim zaman uyumsuz yöntemde bir'e await
ulaştığında, beklenen görev tamamlanana kadar yöntemdeki ilerleme askıya alınır. Görev tamamlandığında, yürütme yönteminde devam edebilir. Daha fazla bilgi için bkz. Async ve await ile zaman uyumsuz programlama.
Uygulanan tamamlanmış görev, görevi döndüren await
yöntemde işlenmeyen bir özel durum nedeniyle hatalı durumda olabilir. Görevin beklenmesi bir özel durum oluşturur. Görev, döndüren zaman uyumsuz işlem iptal edilirse de iptal edilmiş duruma gelebilir. İptal edilmiş bir görev beklenildiğinde bir OperationCanceledException
oluşturur.
Özel durumu yakalamak için, görevi bir try
blokta bekleyin ve ilişkili catch
blokta özel durumu yakalayın. Bir örnek için Zaman uyumsuz yöntem örneği bölümüne bakın.
Beklenen zaman uyumsuz yöntemde birden çok özel durum oluştuğundan bir görev hatalı durumda olabilir. Örneğin, görev çağrısının Task.WhenAllsonucu olabilir. Böyle bir görevi beklediğiniz zaman, özel durumlardan yalnızca biri yakalanıyor ve hangi özel durumun yakalanacağını tahmin edemiyoruz. Örnek için Task.WhenAll örnek bölümüne bakın.
Örnek
Aşağıdaki örnekte, try
blok bir özel duruma neden olabilecek yöntemine ProcessString
bir çağrı içerir. catch
yan tümcesi, yalnızca ekranda bir ileti görüntüleyen özel durum işleyicisini içerir. throw
deyimi içinde ProcessString
çağrıldığında sistem deyimini catch
arar ve iletisini Exception caught
görüntüler.
class TryFinallyTest
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException(paramName: nameof(s), message: "parameter can't be null.");
}
}
public static void Main()
{
string s = null; // For demonstration purposes.
try
{
ProcessString(s);
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at TryFinallyTest.Main() Exception caught.
* */
İki catch bloğu örneği
Aşağıdaki örnekte iki catch bloğu kullanılmıştır ve ilk gelen en özel durum yakalanmış olur.
En az belirli bir özel durumu yakalamak için içindeki throw deyimini ProcessString
aşağıdaki deyimle değiştirebilirsiniz: throw new Exception()
.
Örnekte en az özel catch bloğunu önce yerleştirirseniz, aşağıdaki hata iletisi görüntülenir: A previous catch clause already catches all exceptions of this or a super type ('System.Exception')
.
class ThrowTest3
{
static void ProcessString(string s)
{
if (s == null)
{
throw new ArgumentNullException(paramName: nameof(s), message: "Parameter can't be null");
}
}
public static void Main()
{
try
{
string s = null;
ProcessString(s);
}
// Most specific:
catch (ArgumentNullException e)
{
Console.WriteLine("{0} First exception caught.", e);
}
// Least specific:
catch (Exception e)
{
Console.WriteLine("{0} Second exception caught.", e);
}
}
}
/*
Output:
System.ArgumentNullException: Value cannot be null.
at Test.ThrowTest3.ProcessString(String s) ... First exception caught.
*/
Zaman uyumsuz yöntem örneği
Aşağıdaki örnekte zaman uyumsuz yöntemler için özel durum işleme gösterilmektedir. Zaman uyumsuz bir görevin attığı bir özel durumu yakalamak için, ifadeyi bir try
bloğun await
içine yerleştirin ve özel durumu bir catch
blokta yakalayın.
Özel durum işlemeyi throw new Exception
göstermek için örnekteki satırın açıklamasını kaldırın. IsFaulted
Görevin özelliği olarak ayarlanırTrue
, görevin Exception.InnerException
özelliği özel durum olarak ayarlanır ve özel durum bloğuna catch
yakalanılır.
Zaman uyumsuz bir işlemi iptal ettiğinizde ne olduğunu göstermek için satırın açıklamasını throw new OperationCanceledException
kaldırın. Görevin IsCanceled
özelliği olarak true
ayarlanır ve özel durum bloğunda catch
yakalanmış olur. Bu örnekte geçerli olmayan bazı koşullar altında, görevin IsFaulted
özelliği olarak ayarlanır true
ve IsCanceled
olarak false
ayarlanır.
public async Task DoSomethingAsync()
{
Task<string> theTask = DelayAsync();
try
{
string result = await theTask;
Debug.WriteLine("Result: " + result);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Message: " + ex.Message);
}
Debug.WriteLine("Task IsCanceled: " + theTask.IsCanceled);
Debug.WriteLine("Task IsFaulted: " + theTask.IsFaulted);
if (theTask.Exception != null)
{
Debug.WriteLine("Task Exception Message: "
+ theTask.Exception.Message);
Debug.WriteLine("Task Inner Exception Message: "
+ theTask.Exception.InnerException.Message);
}
}
private async Task<string> DelayAsync()
{
await Task.Delay(100);
// Uncomment each of the following lines to
// demonstrate exception handling.
//throw new OperationCanceledException("canceled");
//throw new Exception("Something happened.");
return "Done";
}
// Output when no exception is thrown in the awaited method:
// Result: Done
// Task IsCanceled: False
// Task IsFaulted: False
// Output when an Exception is thrown in the awaited method:
// Exception Message: Something happened.
// Task IsCanceled: False
// Task IsFaulted: True
// Task Exception Message: One or more errors occurred.
// Task Inner Exception Message: Something happened.
// Output when a OperationCanceledException or TaskCanceledException
// is thrown in the awaited method:
// Exception Message: canceled
// Task IsCanceled: True
// Task IsFaulted: False
Task.WhenAll örneği
Aşağıdaki örnekte, birden çok görevin birden çok özel duruma neden olabileceği özel durum işleme gösterilmektedir. try
bloğu, çağrısı Task.WhenAlltarafından döndürülen görevi bekler. WhenAll'ın uygulandığı üç görev tamamlandığında görev tamamlanır.
Üç görevden her biri bir özel duruma neden olur. catch
Blok, tarafından Task.WhenAlldöndürülen görevin özelliğinde Exception.InnerExceptions
bulunan özel durumlar arasında yinelenir.
public async Task DoMultipleAsync()
{
Task theTask1 = ExcAsync(info: "First Task");
Task theTask2 = ExcAsync(info: "Second Task");
Task theTask3 = ExcAsync(info: "Third Task");
Task allTasks = Task.WhenAll(theTask1, theTask2, theTask3);
try
{
await allTasks;
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex.Message);
Debug.WriteLine("Task IsFaulted: " + allTasks.IsFaulted);
foreach (var inEx in allTasks.Exception.InnerExceptions)
{
Debug.WriteLine("Task Inner Exception: " + inEx.Message);
}
}
}
private async Task ExcAsync(string info)
{
await Task.Delay(100);
throw new Exception("Error-" + info);
}
// Output:
// Exception: Error-First Task
// Task IsFaulted: True
// Task Inner Exception: Error-First Task
// Task Inner Exception: Error-Second Task
// Task Inner Exception: Error-Third Task
C# dili belirtimi
Daha fazla bilgi için C# dil belirtiminintry deyimi bölümüne bakın.