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.Datanullç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 OperationCanceledExceptionoluş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 caughtgö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 trueayarlanı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 falseayarlanı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.

Ayrıca bkz.