Aracılığıyla paylaş


System.Exception sınıfı

Bu makale, bu API'nin başvuru belgelerine ek açıklamalar sağlar.

Exception sınıfı, tüm özel durumlar için temel sınıftır. Bir hata oluştuğunda, sistem veya şu anda yürütülen uygulama, hata hakkında bilgi içeren bir özel durum oluşturarak bunu bildirir. Bir özel durum oluşturulduktan sonra uygulama veya varsayılan özel durum işleyicisi tarafından işlenir.

Hatalar ve özel durumlar

Çalışma zamanı hataları çeşitli nedenlerle oluşabilir. Ancak, tüm hatalar kodunuzda özel durum olarak işlenmemelidir. Çalışma zamanında oluşabilecek bazı hata kategorileri ve bunlara yanıt vermenin uygun yolları aşağıdadır.

  • Kullanım hataları. Kullanım hatası, program mantığındaki özel duruma neden olabilecek bir hatayı temsil eder. Ancak hata, özel durum işleme yoluyla değil, hatalı kodu değiştirerek giderilmelidir. Örneğin, aşağıdaki örnekteki Object.Equals(Object) yönteminin geçersiz kılınması, obj bağımsız değişkeninin her zaman null olmaması gerektiğini varsayar.

    using System;
    
    public class Person1
    {
       private string _name;
    
       public string Name
       {
          get { return _name; }
          set { _name = value; }
       }
    
       public override int GetHashCode()
       {
          return this.Name.GetHashCode();
       }
    
       public override bool Equals(object obj)
       {
          // This implementation contains an error in program logic:
          // It assumes that the obj argument is not null.
          Person1 p = (Person1) obj;
          return this.Name.Equals(p.Name);
       }
    }
    
    public class UsageErrorsEx1
    {
       public static void Main()
       {
          Person1 p1 = new Person1();
          p1.Name = "John";
          Person1 p2 = null;
    
          // The following throws a NullReferenceException.
          Console.WriteLine($"p1 = p2: {p1.Equals(p2)}");
       }
    }
    
    // In F#, null is not a valid state for declared types 
    // without 'AllowNullLiteralAttribute'
    [<AllowNullLiteral>]
    type Person() =
        member val Name = "" with get, set
    
        override this.GetHashCode() =
            this.Name.GetHashCode()
    
        override this.Equals(obj) =
            // This implementation contains an error in program logic:
            // It assumes that the obj argument is not null.
            let p = obj :?> Person
            this.Name.Equals p.Name
    
    let p1 = Person()
    p1.Name <- "John"
    let p2: Person = null
    
    // The following throws a NullReferenceException.
    printfn $"p1 = p2: {p1.Equals p2}"
    
    Public Class Person
       Private _name As String
       
       Public Property Name As String
          Get
             Return _name
          End Get
          Set
             _name = value
          End Set
       End Property
       
       Public Overrides Function Equals(obj As Object) As Boolean
          ' This implementation contains an error in program logic:
          ' It assumes that the obj argument is not null.
          Dim p As Person = CType(obj, Person)
          Return Me.Name.Equals(p.Name)
       End Function
    End Class
    
    Module Example2
        Public Sub Main()
            Dim p1 As New Person()
            p1.Name = "John"
            Dim p2 As Person = Nothing
    
            ' The following throws a NullReferenceException.
            Console.WriteLine("p1 = p2: {0}", p1.Equals(p2))
        End Sub
    End Module
    

    Kaynak kodu, NullReferenceException geçersiz kılmadan önce null için açıkça test edilecek şekilde değiştirilip yeniden derlendiğinde obj sırasında sonuçlanan null istisnası ortadan kaldırılabilir. Aşağıdaki örnek, bir null bağımsız değişkeni işleyen düzeltilmiş kaynak kodunu içerir.

    using System;
    
    public class Person2
    {
        private string _name;
    
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    
        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }
    
        public override bool Equals(object obj)
        {
            // This implementation handles a null obj argument.
            Person2 p = obj as Person2;
            if (p == null)
                return false;
            else
                return this.Name.Equals(p.Name);
        }
    }
    
    public class UsageErrorsEx2
    {
        public static void Main()
        {
            Person2 p1 = new Person2();
            p1.Name = "John";
            Person2 p2 = null;
    
            Console.WriteLine($"p1 = p2: {p1.Equals(p2)}");
        }
    }
    // The example displays the following output:
    //        p1 = p2: False
    
    // In F#, null is not a valid state for declared types 
    // without 'AllowNullLiteralAttribute'
    [<AllowNullLiteral>]
    type Person() =
        member val Name = "" with get, set
    
        override this.GetHashCode() =
            this.Name.GetHashCode()
    
        override this.Equals(obj) =
            // This implementation handles a null obj argument.
            match obj with
            | :? Person as p -> 
                this.Name.Equals p.Name
            | _ ->
                false
    
    let p1 = Person()
    p1.Name <- "John"
    let p2: Person = null
    
    printfn $"p1 = p2: {p1.Equals p2}"
    // The example displays the following output:
    //        p1 = p2: False
    
    Public Class Person2
        Private _name As String
    
        Public Property Name As String
            Get
                Return _name
            End Get
            Set
                _name = Value
            End Set
        End Property
    
        Public Overrides Function Equals(obj As Object) As Boolean
            ' This implementation handles a null obj argument.
            Dim p As Person2 = TryCast(obj, Person2)
            If p Is Nothing Then
                Return False
            Else
                Return Me.Name.Equals(p.Name)
            End If
        End Function
    End Class
    
    Module Example3
        Public Sub Main()
            Dim p1 As New Person2()
            p1.Name = "John"
            Dim p2 As Person2 = Nothing
    
            Console.WriteLine("p1 = p2: {0}", p1.Equals(p2))
        End Sub
    End Module
    ' The example displays the following output:
    '       p1 = p2: False
    

    Hata ayıklama derlemelerindeki kullanım hatalarını tanımlamak için Debug.Assert yöntemini ve hem hata ayıklama hem de yayın derlemelerindeki kullanım hatalarını belirlemek için Trace.Assert yöntemini kullanabilir, kullanım hataları için özel durum işleme kullanmaktan kaçınabilirsiniz. Daha fazla bilgi için bkz. Yönetilen Kodda Onaylar.

  • Program hataları. Program hatası, hatasız kod yazarak mutlaka kaçınılamayan bir çalışma zamanı hatasıdır.

    Bazı durumlarda, program hatası beklenen veya rutin bir hata koşulunu yansıtabilir. Bu durumda, program hatasıyla başa çıkmak için özel durum işleme kullanmaktan kaçınmak ve bunun yerine işlemi yeniden denemek isteyebilirsiniz. Örneğin, kullanıcının belirli bir biçimde tarih girmesi bekleniyorsa, DateTime.TryParseExact yöntemini çağırarak tarih dizesini ayrıştırabilirsiniz. Bu yöntem, ayrıştırma işleminin başarılı olup olmadığını gösteren bir Boolean değer döndürür. Tarih dizesi bir DateTime.ParseExact değerine dönüştürülemezse, FormatException istisnası oluşturan DateTime yöntemini kullanmak yerine bu yaklaşımı tercih edin. Benzer şekilde, bir kullanıcı var olmayan bir dosyayı açmaya çalışırsa, önce dosyanın var olup olmadığını denetlemek için yöntemini çağırabilir File.Exists ve yoksa, kullanıcıya oluşturmak isteyip istemediğini sorabilirsiniz.

    Diğer durumlarda, program hatası kodunuzda işlenebilen beklenmeyen bir hata koşulunu yansıtır. Örneğin, bir dosyanın var olduğundan emin olmak için denetlemiş olsanız bile, dosyayı açabilmeniz için önce silinebilir veya bozulmuş olabilir. Bu durumda, bir StreamReader nesne örneği oluşturarak veya Open yöntemini çağırarak dosyayı açmaya çalışmak bir FileNotFoundException özel durumu fırlatabilir. Bu gibi durumlarda, hatadan kurtarmak için özel durum işlemeyi kullanmanız gerekir.

  • Sistem hataları. Sistem hatası, program aracılığıyla anlamlı bir şekilde işlenemeyen bir çalışma zamanı hatasıdır. Örneğin, ortak dil çalışma zamanı ek bellek ayıramıyorsa herhangi bir yöntem bir OutOfMemoryException istisnası oluşturabilir. Normalde sistem hataları özel durum işleme kullanılarak işlenmez. Bunun yerine, uygulama sonlandırılmadan önce özel durum bilgilerini günlüğe kaydetmek ve kullanıcıya hatayı bildirmek için AppDomain.UnhandledException gibi bir olayı kullanabilir ve Environment.FailFast yöntemini çağırabilirsiniz.

Try/catch blokları

Ortak dil çalışma zamanı, özel durumların nesneler olarak temsilini ve program kodu ile özel durum işleme try kodunun bloklara ve catch bloklara ayrılmasını temel alan bir özel durum işleme modeli sağlar. Her biri belirli bir özel durum türünü işlemek üzere tasarlanmış bir veya daha fazla catch blok veya başka bir bloktan daha özel bir özel durum yakalamak için tasarlanmış bir blok olabilir.

Bir uygulama, bir uygulama kodu bloğunun yürütülmesi sırasında oluşan özel durumları işlerse, kod bir try deyimi içine yerleştirilmelidir ve blok olarak adlandırılır try . Bir try blok tarafından oluşturulan özel durumları işleyen uygulama kodu, bir catch deyimi içine yerleştirilir ve catch bloğu olarak adlandırılır. Sıfır veya daha fazla catch blok bir try blokla ilişkilendirilir ve her catch blok, işlediği özel durum türlerini belirleyen bir tür filtresi içerir.

Bir try blokta özel durum oluştuğunda sistem, özel durumu işleyen bir catch blok bulana kadar ilişkili catch blokları uygulama kodunda göründükleri sırayla arar. Bir catch bloğu, catch bloğunun tür filtresi T veya ondan türeyen herhangi bir tür ise T türündeki bir özel durumu işler. Sistem, özel durumu işleyen ilk catch bloğu bulduklarından sonra aramayı durdurur. Bu nedenle, uygulama kodunda, bu bölümü izleyen örnekte gösterildiği gibi, catch bir türü işleyen bir bloğun temel türlerini işleyen bir catch blok öncesinde belirtilmesi gerekir. System.Exception işlemek üzere bir catch bloğu en son belirtilir.

Geçerli catch blokla ilişkili try blokların hiçbiri istisnayı işlemezse, ve geçerli try blok geçerli çağrıdaki diğer try blokların içinde iç içe yerleştirilmişse, bir sonraki kapsayıcı catch blokla ilişkili try bloklar aranır. Özel durum için bir catch blok bulunmazsa, sistem mevcut çağrı içindeki önceki iç içe yerleştirme seviyelerini arar. Geçerli çağrıda özel durum için hiçbir catch blok bulunmazsa, özel durum çağrı yığınına geçirilir ve önceki yığın çerçevesi özel durumu işleyen bir catch blok için aranılır. Çağrı yığını araması, özel durum işlenene kadar veya çağrı yığınında başka çerçeve kalmayıncaya kadar devam eder. Çağrı yığınının en üstüne özel durumu işleyen bir catch blok bulunmaksızın ulaşılırsa, varsayılan özel durum işleyicisi bunu işler ve uygulama sonlandırılır.

F# deneyin.. ifade ile

F# blokları kullanmaz catch . Bunun yerine, yükseltilmiş bir özel durum deseni tek with bir blok kullanılarak eşleştirilir. Bu bir ifade olduğundan, tüm yolların aynı türü döndürmesi gerekir. Daha fazla bilgi edinmek için bkz. try...with ifadesi.

Özel durum türü özellikleri

Özel durum türleri aşağıdaki özellikleri destekler:

  • Hatayı açıklayan, okunabilir metin. Bir özel durum oluştuğunda, çalışma zamanı kullanıcıyı hatanın doğası hakkında bilgilendirmek ve sorunu çözmek için eylem önermek için bir kısa mesaj sağlar. Bu metin iletisi özel durum nesnesinin özelliğinde Message tutulur. Özel durum nesnesinin oluşturulması sırasında, bu özel durumun ayrıntılarını açıklamak için oluşturucuya bir metin dizesi geçirebilirsiniz. Oluşturucuya bir hata mesajı argümanı sağlanmadıysa, varsayılan hata mesajı kullanılır. Daha fazla bilgi için Message özelliğine bakın.

  • İstisna fırlatıldığında çağrı yığınının durumu. özelliği, StackTrace hatanın kodda nerede oluştuğuna karar vermek için kullanılabilecek bir yığın izlemesi taşır. Yığın izlemesi, çağrılan tüm yöntemleri ve çağrıların yapıldığı kaynak dosyadaki satır numaralarını listeler.

İstisna sınıfı özellikleri

sınıfı Exception , kod konumunu, türünü, yardım dosyasını ve özel durumun nedenini tanımlamaya yardımcı olan bir dizi özellik içerir: StackTrace, InnerException, Message, HelpLink, HResult, , Source, TargetSiteve Data.

İki veya daha fazla özel durum arasında nedensel ilişki varsa, InnerException özelliği bu bilgileri korur. Dış özel durum, bu iç özel duruma yanıt olarak oluşturulur. Dış özel durumu işleyen kod, hatayı daha uygun bir şekilde işlemek için önceki iç özel durumdaki bilgileri kullanabilir. Özel durumla ilgili ek bilgiler, özelliğinde Data anahtar/değer çiftleri koleksiyonu olarak depolanabilir.

Özel durum nesnesi oluşturulurken oluşturucuya geçirilen hata iletisi dizesi yerelleştirilmelidir ve sınıfı kullanılarak bir kaynak dosyasından ResourceManager sağlanabilir. Yerelleştirilmiş kaynaklar hakkında daha fazla bilgi için Uydu Derlemeleri Oluşturma ve Kaynakları Paketleme ve Dağıtma konularına bakın.

Kullanıcıya özel durumun neden oluştuğu hakkında kapsamlı bilgiler sağlamak için, özellik bir yardım dosyasının HelpLink URL'sini (veya URN'sini) tutabilir.

Exception sınıfı, 0x80131500 değerine sahip olan HRESULT COR_E_EXCEPTION'ü kullanır.

Sınıfının bir örneğinin ilk özellik değerlerinin Exception listesi için oluşturuculara Exception bakın.

Performansla ilgili dikkat edilmesi gerekenler

Özel durum oluşturma veya işleme, önemli miktarda sistem kaynağı ve yürütme süresi tüketir. Öngörülebilir olayları veya akış kontrolünü yönetmek için değil, yalnızca gerçekten olağanüstü durumları ele almak için istisnalar atın. Örneğin, bir sınıf kitaplığı geliştirirken olduğu gibi bazı durumlarda, yönteminizin geçerli parametrelerle çağrılmasını beklediğiniz için bir yöntem bağımsız değişkeni geçersizse bir özel durum oluşturmak mantıklıdır. Geçersiz bir yöntem bağımsız değişkeni, eğer bir kullanım hatasının sonucu değilse, olağanüstü bir şey yaşandığı anlamına gelir. Buna karşılık, kullanıcı girişi geçersizse bir özel durum oluşturmayın, çünkü kullanıcıların bazen geçersiz veri girmesini bekleyebilirsiniz. Bunun yerine, kullanıcıların geçerli giriş girebilmesi için bir yeniden deneme mekanizması sağlayın. Kullanım hatalarını işlemek için özel durumları da kullanmamalısınız. Bunun yerine, kullanım hatalarını tanımlamak ve düzeltmek için doğrulama kullanın.

Ayrıca, bir dönüş kodu yeterli olduğunda özel durum oluşturmayın; dönüş kodunu özel duruma dönüştürmeyin; ve rutin olarak bir özel durum yakalamayın, yok saymayın ve işlemeye devam etmeyin.

Özel durumu yeniden oluşturma

Çoğu durumda, bir özel durum işleyicisi sadece istisnayı çağırana iletmek ister. Bu en sık şu durumlarda oluşur:

  • .NET sınıf kitaplığındaki veya diğer sınıf kitaplıklarındaki yöntemlere çağrıları saran bir sınıf kitaplığı.

  • Ölümcül bir özel durumla karşılaşan bir uygulama veya kitaplık. Özel durum işleyicisi özel durumu günlüğe kaydedebilir ve ardından özel durumu yeniden fırlatabilir.

Bir özel durumu yeniden oluşturmanın önerilen yolu C# dilinde throw deyimini, F# dilinde reraise işlevini ve Bir ifade eklemeden Visual Basic'te Throw deyimini kullanmaktır. Bu, özel durum çağırana yayıldığında tüm çağrı yığını bilgilerinin korunmasını sağlar. Aşağıdaki örnekte bu gösterilmektedir. dize uzantısı yöntemi, bağımsız değişkenlerini önceden doğrulamadan bir veya daha fazla FindOccurrences çağrısını String.IndexOf(String, Int32) içine sarar.

using System;
using System.Collections.Generic;

public static class Library1
{
    public static int[] FindOccurrences(this String s, String f)
    {
        var indexes = new List<int>();
        int currentIndex = 0;
        try
        {
            while (currentIndex >= 0 && currentIndex < s.Length)
            {
                currentIndex = s.IndexOf(f, currentIndex);
                if (currentIndex >= 0)
                {
                    indexes.Add(currentIndex);
                    currentIndex++;
                }
            }
        }
        catch (ArgumentNullException)
        {
            // Perform some action here, such as logging this exception.

            throw;
        }
        return indexes.ToArray();
    }
}
open System

module Library = 
    let findOccurrences (s: string) (f: string) =
        let indexes = ResizeArray()
        let mutable currentIndex = 0
        try
            while currentIndex >= 0 && currentIndex < s.Length do
                currentIndex <- s.IndexOf(f, currentIndex)
                if currentIndex >= 0 then
                    indexes.Add currentIndex
                    currentIndex <- currentIndex + 1
        with :? ArgumentNullException ->
            // Perform some action here, such as logging this exception.
            reraise ()
        indexes.ToArray()
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module Library
    <Extension()>
    Public Function FindOccurrences1(s As String, f As String) As Integer()
        Dim indexes As New List(Of Integer)
        Dim currentIndex As Integer = 0
        Try
            Do While currentIndex >= 0 And currentIndex < s.Length
                currentIndex = s.IndexOf(f, currentIndex)
                If currentIndex >= 0 Then
                    indexes.Add(currentIndex)
                    currentIndex += 1
                End If
            Loop
        Catch e As ArgumentNullException
            ' Perform some action here, such as logging this exception.

            Throw
        End Try
        Return indexes.ToArray()
    End Function
End Module

Bir arayan daha sonra iki kez arar FindOccurrences . FindOccurrences öğesine yapılan ikinci çağrıda, çağıran bir null arama dizesi olarak geçirir ve bu da String.IndexOf(String, Int32) yönteminin bir ArgumentNullException özel durum fırlatmasına neden olur. Bu istisna, FindOccurrences yöntemi tarafından ele alınır ve çağırana geri iletilir. Throw deyimi ifade olmadan kullanıldığından, örnekteki çıkış çağrı yığınının korunduğunu gösterir.

public class RethrowEx1
{
    public static void Main()
    {
        String s = "It was a cold day when...";
        int[] indexes = s.FindOccurrences("a");
        ShowOccurrences(s, "a", indexes);
        Console.WriteLine();

        String toFind = null;
        try
        {
            indexes = s.FindOccurrences(toFind);
            ShowOccurrences(s, toFind, indexes);
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine($"An exception ({e.GetType().Name}) occurred.");
            Console.WriteLine($"Message:{Environment.NewLine}   {e.Message}{Environment.NewLine}");
            Console.WriteLine($"Stack Trace:{Environment.NewLine}   {e.StackTrace}{Environment.NewLine}");
        }
    }

    private static void ShowOccurrences(String s, String toFind, int[] indexes)
    {
        Console.Write("'{0}' occurs at the following character positions: ",
                      toFind);
        for (int ctr = 0; ctr < indexes.Length; ctr++)
            Console.Write("{0}{1}", indexes[ctr],
                          ctr == indexes.Length - 1 ? "" : ", ");

        Console.WriteLine();
    }
}
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//    Message:
//       Value cannot be null.
//    Parameter name: value
//
//    Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)
//       at Example.Main()
open Library

let showOccurrences toFind (indexes: int[]) =
    printf $"'{toFind}' occurs at the following character positions: "
    for i = 0 to indexes.Length - 1 do
        printf $"""{indexes[i]}{if i = indexes.Length - 1 then "" else ", "}"""
    printfn ""

let s = "It was a cold day when..."
let indexes = findOccurrences s "a"
showOccurrences "a" indexes
printfn ""

let toFind: string = null
try
    let indexes = findOccurrences s toFind
    showOccurrences toFind indexes

with :? ArgumentNullException as e ->
    printfn $"An exception ({e.GetType().Name}) occurred."
    printfn $"Message:\n   {e.Message}\n"
    printfn $"Stack Trace:\n   {e.StackTrace}\n"

// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//    Message:
//       Value cannot be null. (Parameter 'value')
//
//    Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.findOccurrences(String s, String f)
//       at <StartupCode$fs>.main@()
Module Example1
    Public Sub Main()
        Dim s As String = "It was a cold day when..."
        Dim indexes() As Integer = s.FindOccurrences1("a")
        ShowOccurrences(s, "a", indexes)
        Console.WriteLine()

        Dim toFind As String = Nothing
        Try
            indexes = s.FindOccurrences1(toFind)
            ShowOccurrences(s, toFind, indexes)
        Catch e As ArgumentNullException
            Console.WriteLine("An exception ({0}) occurred.",
                           e.GetType().Name)
            Console.WriteLine("Message:{0}   {1}{0}", vbCrLf, e.Message)
            Console.WriteLine("Stack Trace:{0}   {1}{0}", vbCrLf, e.StackTrace)
        End Try
    End Sub

    Private Sub ShowOccurrences(s As String, toFind As String, indexes As Integer())
        Console.Write("'{0}' occurs at the following character positions: ",
                    toFind)
        For ctr As Integer = 0 To indexes.Length - 1
            Console.Write("{0}{1}", indexes(ctr),
                       If(ctr = indexes.Length - 1, "", ", "))
        Next
        Console.WriteLine()
    End Sub
End Module
' The example displays the following output:
'    'a' occurs at the following character positions: 4, 7, 15
'
'    An exception (ArgumentNullException) occurred.
'    Message:
'       Value cannot be null.
'    Parameter name: value
'
'    Stack Trace:
'          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
'    ngComparison comparisonType)
'       at Library.FindOccurrences(String s, String f)
'       at Example.Main()

Buna karşılık, özel durum bu ifade kullanılarak yeniden atılırsa:

throw e;
Throw e
raise e

... ardından tam çağrı yığını korunmaz ve örnek aşağıdaki çıkışı oluşturur:

'a' occurs at the following character positions: 4, 7, 15

An exception (ArgumentNullException) occurred.
Message:
   Value cannot be null.
Parameter name: value

Stack Trace:
      at Library.FindOccurrences(String s, String f)
   at Example.Main()

Biraz daha hantal bir alternatif, yeni bir özel durum oluşturmak ve özgün özel durumun çağrı yığını bilgilerini bir iç özel durumda korumaktır. Çağıran daha sonra yığın çerçevesini ve özgün özel durum hakkındaki diğer bilgileri almak için yeni özel durumun InnerException özelliğini kullanabilir. Bu durumda throw deyimi şöyledir:

throw new ArgumentNullException("You must supply a search string.", e);
raise (ArgumentNullException("You must supply a search string.", e) )
Throw New ArgumentNullException("You must supply a search string.",
                             e)

Aşağıdaki özel durum işleyicisinde gösterildiği gibi, özel durumu işleyen kullanıcı kodunun InnerException özelliğin özgün özel durum hakkında bilgi içerdiğini bilmesi gerekir.

try
{
    indexes = s.FindOccurrences(toFind);
    ShowOccurrences(s, toFind, indexes);
}
catch (ArgumentNullException e)
{
    Console.WriteLine($"An exception ({e.GetType().Name}) occurred.");
    Console.WriteLine($"   Message:{Environment.NewLine}{e.Message}");
    Console.WriteLine($"   Stack Trace:{Environment.NewLine}   {e.StackTrace}");
    Exception ie = e.InnerException;
    if (ie != null)
    {
        Console.WriteLine("   The Inner Exception:");
        Console.WriteLine($"      Exception Name: {ie.GetType().Name}");
        Console.WriteLine($"      Message: {ie.Message}{Environment.NewLine}");
        Console.WriteLine($"      Stack Trace:{Environment.NewLine}   {ie.StackTrace}{Environment.NewLine}");
    }
}
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//       Message: You must supply a search string.
//
//       Stack Trace:
//          at Library.FindOccurrences(String s, String f)
//       at Example.Main()
//
//       The Inner Exception:
//          Exception Name: ArgumentNullException
//          Message: Value cannot be null.
//    Parameter name: value
//
//          Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)
try
    let indexes = findOccurrences s toFind
    showOccurrences toFind indexes
with :? ArgumentNullException as e ->
    printfn $"An exception ({e.GetType().Name}) occurred."
    printfn $"   Message:\n{e.Message}"
    printfn $"   Stack Trace:\n   {e.StackTrace}"
    let ie = e.InnerException
    if ie <> null then
        printfn "   The Inner Exception:"
        printfn $"      Exception Name: {ie.GetType().Name}"
        printfn $"      Message: {ie.Message}\n"
        printfn $"      Stack Trace:\n   {ie.StackTrace}\n"
// The example displays the following output:
//    'a' occurs at the following character positions: 4, 7, 15
//
//    An exception (ArgumentNullException) occurred.
//       Message: You must supply a search string.
//
//       Stack Trace:
//          at Library.FindOccurrences(String s, String f)
//       at Example.Main()
//
//       The Inner Exception:
//          Exception Name: ArgumentNullException
//          Message: Value cannot be null.
//    Parameter name: value
//
//          Stack Trace:
//          at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
//    ngComparison comparisonType)
//       at Library.FindOccurrences(String s, String f)
Try
    indexes = s.FindOccurrences(toFind)
    ShowOccurrences(s, toFind, indexes)
Catch e As ArgumentNullException
    Console.WriteLine("An exception ({0}) occurred.",
                   e.GetType().Name)
    Console.WriteLine("   Message: {1}{0}", vbCrLf, e.Message)
    Console.WriteLine("   Stack Trace:{0}   {1}{0}", vbCrLf, e.StackTrace)
    Dim ie As Exception = e.InnerException
    If ie IsNot Nothing Then
        Console.WriteLine("   The Inner Exception:")
        Console.WriteLine("      Exception Name: {0}", ie.GetType().Name)
        Console.WriteLine("      Message: {1}{0}", vbCrLf, ie.Message)
        Console.WriteLine("      Stack Trace:{0}   {1}{0}", vbCrLf, ie.StackTrace)
    End If
End Try
' The example displays the following output:
'       'a' occurs at the following character positions: 4, 7, 15
'
'       An exception (ArgumentNullException) occurred.
'          Message: You must supply a search string.
'
'          Stack Trace:
'             at Library.FindOccurrences(String s, String f)
'          at Example.Main()
'
'          The Inner Exception:
'             Exception Name: ArgumentNullException
'             Message: Value cannot be null.
'       Parameter name: value
'
'             Stack Trace:
'             at System.String.IndexOf(String value, Int32 startIndex, Int32 count, Stri
'       ngComparison comparisonType)
'          at Library.FindOccurrences(String s, String f)

Standart özel durumları seçme

Özel durum oluşturmanız gerektiğinde, özel bir özel durum uygulamak yerine .NET'te var olan bir özel durum türünü kullanabilirsiniz. Şu iki koşul altında standart bir özel durum türü kullanmalısınız:

  • Bir kullanım hatasının (yani, yönteminizi çağıran geliştirici tarafından yapılan program mantığındaki bir hatanın) neden olduğu bir istisna fırlatıyorsunuz. Genellikle ArgumentException, ArgumentNullException, InvalidOperationException veya NotSupportedException gibi bir özel durum fırlatırsınız. Özel durum nesnesinin örneğini oluştururken özel durum nesnesinin oluşturucusunun sağladığınız dize, geliştiricinin düzeltebilmesi için hatayı açıklamalıdır. Daha fazla bilgi için Message özelliğine bakın.

  • Var olan bir .NET özel durumuyla çağırana iletilebilen bir hatayı işliyorsunuz. Mümkün olan en türetilmiş özel durumu fırlatmalısınız. Örneğin, bir yöntem bir bağımsız değişkenin bir sabit listesi türünün geçerli bir üyesi olmasını gerektiriyorsa, bir InvalidEnumArgumentException yerine bir ArgumentException (en türetilmiş sınıf) oluşturmanız gerekir.

Aşağıdaki tabloda yaygın istisna türleri ve hangi koşullarda fırlatılacağı listelenmiştir.

İstisna Koşul
ArgumentException Bir yönteme geçirilen null olmayan bağımsız değişken geçersiz.
ArgumentNullException Bir yönteme geçirilen bağımsız değişken: null.
ArgumentOutOfRangeException Bir argüman geçerli değer aralığının dışındadır.
DirectoryNotFoundException Dizin yolunun bir bölümü geçerli değil.
DivideByZeroException Tamsayı veya Decimal bölme işlemindeki payda sıfırdır.
DriveNotFoundException Disk kullanılamıyor veya mevcut değil.
FileNotFoundException Dosya yok.
FormatException Değer, Parse gibi bir dönüştürme yöntemiyle bir dizeden dönüştürülebilecek uygun biçimde değildir.
IndexOutOfRangeException Bir dizin, bir dizi veya koleksiyonun sınırlarının dışında.
InvalidOperationException Yöntem çağrısı, nesnenin geçerli durumunda geçersiz.
KeyNotFoundException Koleksiyondaki bir üyeye erişmek için belirtilen anahtar bulunamıyor.
NotImplementedException Yöntem veya işlem uygulanmaz.
NotSupportedException Yöntem veya işlem desteklenmez.
ObjectDisposedException Yok edilmiş bir nesne üzerinde bir işlem gerçekleştirilir.
OverflowException Aritmetik, türetme veya dönüştürme işlemi taşmayla sonuçlanmasıdır.
PathTooLongException Yol veya dosya adı, sistem tanımlı uzunluk üst sınırını aşıyor.
PlatformNotSupportedException İşlem geçerli platformda desteklenmiyor.
RankException Bir yönteme yanlış sayıda boyuta sahip bir dizi geçirilir.
TimeoutException Bir işleme ayrılan zaman aralığının süresi doldu.
UriFormatException Geçersiz bir Tekdüzen Kaynak Tanımlayıcısı (URI) kullanılıyor.

Özel istisnalar uygulama

Aşağıdaki durumlarda, bir hata koşulunu işlemek için mevcut bir .NET özel durumunu kullanmak yeterli değildir:

  • Özel durum, mevcut bir .NET özel durumuyla eşlenemeyen benzersiz bir program hatasını yansıttığında.

  • Özel durum, var olan bir .NET özel durumu için uygun işlemeden farklı bir işleme gerektirdiğinde veya özel durumun benzer bir özel durumdan belirsiz olması gerektiğinde. Örneğin, hedef tam sayı türünün aralığının dışında olan bir dizenin sayısal gösterimini ayrıştırırken özel ArgumentOutOfRangeException durum oluşturursanız, çağıranın yöntemini çağırırken uygun kısıtlanmış değerleri sağlamamasıyla sonuçlanan bir hata için aynı özel durumu kullanmak istemezsiniz.

Exception sınıfı, .NET'teki tüm özel durumların temel sınıfıdır. Birçok türetilmiş sınıf, Exception sınıfının üyelerinin devralınan davranışına dayanır; üyelerini Exception geçersiz kılmaz, benzersiz üyeler de tanımlamaz.

Kendi özel durum sınıfınızı tanımlamak için:

  1. öğesinden Exceptiondevralan bir sınıf tanımlayın. Gerekirse, özel durum hakkında ek bilgi sağlamak için sınıfınızın ihtiyaç duyduğu benzersiz üyeleri tanımlayın. Örneğin, ArgumentException sınıfı, özel duruma neden olan bağımsız değişkenin adını belirten bir ParamName özelliği ve zaman aşımı aralığını belirten bir RegexMatchTimeoutException özelliği içeren bir MatchTimeout özelliği içerir.

  2. Gerekirse, işlevselliğini değiştirmek istediğiniz devralınan üyeleri geçersiz kılın. Çoğu varolan türetilmiş sınıfların Exception devralınan üyelerin davranışını geçersiz kılmadığını unutmayın.

  3. Özelleştirilmiş özel durum nesnenizin serileştirilebilir olup olmadığını belirleyin. Seri hale getirme, özel durum hakkındaki bilgileri kaydetmenizi sağlar ve uzaktan iletişim bağlamında bir sunucu ve istemci proxy'si tarafından özel durum bilgilerinin paylaşılmasına izin verir. Özel durum nesnesini seri hale getirmek için özniteliğiyle SerializableAttribute işaretleyin.

  4. Özel durum sınıfınızın oluşturucularını tanımlayın. Genellikle, özel durum sınıflarının aşağıdaki oluşturuculardan biri veya daha fazlası vardır:

    • Exception(), yeni bir özel durum nesnesinin özelliklerini başlatmak için varsayılan değerleri kullanır.

    • Exception(String), belirtilen hata iletisiyle yeni bir özel durum nesnesi başlatır.

    • Exception(String, Exception), belirtilen hata iletisi ve iç özel durum ile yeni bir özel durum nesnesi başlatır.

    • Exception(SerializationInfo, StreamingContext), serileştirilmiş verilerden yeni bir özel durum nesnesi başlatan bir protected oluşturucudur. Özel durum nesnenizi serileştirilebilir yapmayı seçtiyseniz bu oluşturucuyu uygulamanız gerekir.

Aşağıdaki örnekte özel bir özel durum sınıfının kullanımı gösterilmektedir. İstemci, asal olmayan bir NotPrimeException başlangıç numarası belirterek bir dizi asal sayı almaya çalıştığında oluşan bir özel durum tanımlar. Özel durum, NonPrimeözel duruma neden olan asal olmayan sayıyı döndüren yeni bir özelliği tanımlar. Serileştirme için korumalı bir parametresiz oluşturucu ve SerializationInfo ve StreamingContext parametreleriyle bir oluşturucu uygulamanın yanı sıra, NotPrimeException sınıfı, NonPrime özelliğini desteklemek için üç ek oluşturucu tanımlar. Her oluşturucu, asal olmayan sayının değerini korumaya ek olarak bir temel sınıf oluşturucu çağırır. NotPrimeException sınıfı, SerializableAttribute özniteliğiyle de işaretlenir.

using System;
using System.Runtime.Serialization;

[Serializable()]
public class NotPrimeException : Exception
{
   private int notAPrime;

   protected NotPrimeException()
      : base()
   { }

   public NotPrimeException(int value) :
      base(String.Format("{0} is not a prime number.", value))
   {
      notAPrime = value;
   }

   public NotPrimeException(int value, string message)
      : base(message)
   {
      notAPrime = value;
   }

   public NotPrimeException(int value, string message, Exception innerException) :
      base(message, innerException)
   {
      notAPrime = value;
   }

   protected NotPrimeException(SerializationInfo info,
                               StreamingContext context)
      : base(info, context)
   { }

   public int NonPrime
   { get { return notAPrime; } }
}
namespace global

open System
open System.Runtime.Serialization

[<Serializable>]
type NotPrimeException = 
    inherit Exception
    val notAPrime: int

    member this.NonPrime =
        this.notAPrime

    new (value) =
        { inherit Exception($"%i{value} is not a prime number."); notAPrime = value }

    new (value, message) =
        { inherit Exception(message); notAPrime = value }

    new (value, message, innerException: Exception) =
        { inherit Exception(message, innerException); notAPrime = value }

    // F# does not support protected members
    new () = 
        { inherit Exception(); notAPrime = 0 }

    new (info: SerializationInfo, context: StreamingContext) =
        { inherit Exception(info, context); notAPrime = 0 }
Imports System.Runtime.Serialization

<Serializable()> _
Public Class NotPrimeException : Inherits Exception
   Private notAPrime As Integer

   Protected Sub New()
      MyBase.New()
   End Sub

   Public Sub New(value As Integer)
      MyBase.New(String.Format("{0} is not a prime number.", value))
      notAPrime = value
   End Sub

   Public Sub New(value As Integer, message As String)
      MyBase.New(message)
      notAPrime = value
   End Sub

   Public Sub New(value As Integer, message As String, innerException As Exception)
      MyBase.New(message, innerException)
      notAPrime = value
   End Sub

   Protected Sub New(info As SerializationInfo,
                     context As StreamingContext)
      MyBase.New(info, context)
   End Sub

   Public ReadOnly Property NonPrime As Integer
      Get
         Return notAPrime
      End Get
   End Property
End Class

PrimeNumberGenerator Aşağıdaki örnekte gösterilen sınıf, 2 ile istemci tarafından sınıf oluşturucusunun çağrısında belirtilen sınıra kadar olan asal sayıların dizisini hesaplamak için Eratosthenes Eleği'ni kullanır. yöntemi, GetPrimesFrom belirtilen alt sınırdan büyük veya buna eşit olan tüm asal sayıları döndürür, ancak bu alt sınır bir asal sayı değilse bir NotPrimeException atar.

using System;
using System.Collections.Generic;

[Serializable]
public class PrimeNumberGenerator
{
   private const int START = 2;
   private int maxUpperBound = 10000000;
   private int upperBound;
   private bool[] primeTable;
   private List<int> primes = new List<int>();

   public PrimeNumberGenerator(int upperBound)
   {
      if (upperBound > maxUpperBound)
      {
         string message = String.Format(
                           "{0} exceeds the maximum upper bound of {1}.",
                           upperBound, maxUpperBound);
         throw new ArgumentOutOfRangeException(message);
      }
      this.upperBound = upperBound;
      // Create array and mark 0, 1 as not prime (True).
      primeTable = new bool[upperBound + 1];
      primeTable[0] = true;
      primeTable[1] = true;

      // Use Sieve of Eratosthenes to determine prime numbers.
      for (int ctr = START; ctr <= (int)Math.Ceiling(Math.Sqrt(upperBound));
            ctr++)
      {
         if (primeTable[ctr]) continue;

         for (int multiplier = ctr; multiplier <= upperBound / ctr; multiplier++)
            if (ctr * multiplier <= upperBound) primeTable[ctr * multiplier] = true;
      }
      // Populate array with prime number information.
      int index = START;
      while (index != -1)
      {
         index = Array.FindIndex(primeTable, index, (flag) => !flag);
         if (index >= 1)
         {
            primes.Add(index);
            index++;
         }
      }
   }

   public int[] GetAllPrimes()
   {
      return primes.ToArray();
   }

   public int[] GetPrimesFrom(int prime)
   {
      int start = primes.FindIndex((value) => value == prime);
      if (start < 0)
         throw new NotPrimeException(prime, String.Format("{0} is not a prime number.", prime));
      else
         return primes.FindAll((value) => value >= prime).ToArray();
   }
}
namespace global

open System

[<Serializable>]
type PrimeNumberGenerator(upperBound) =
    let start = 2
    let maxUpperBound = 10000000
    let primes = ResizeArray()
    let primeTable = 
        upperBound + 1
        |> Array.zeroCreate<bool>

    do
        if upperBound > maxUpperBound then
            let message = $"{upperBound} exceeds the maximum upper bound of {maxUpperBound}."
            raise (ArgumentOutOfRangeException message)
        
        // Create array and mark 0, 1 as not prime (True).
        primeTable[0] <- true
        primeTable[1] <- true

        // Use Sieve of Eratosthenes to determine prime numbers.
        for i = start to float upperBound |> sqrt |> ceil |> int do
            if not primeTable[i] then
                for multiplier = i to upperBound / i do
                    if i * multiplier <= upperBound then
                        primeTable[i * multiplier] <- true
        
        // Populate array with prime number information.
        let mutable index = start
        while index <> -1 do
            index <- Array.FindIndex(primeTable, index, fun flag -> not flag)
            if index >= 1 then
                primes.Add index
                index <- index + 1

    member _.GetAllPrimes() =
        primes.ToArray()

    member _.GetPrimesFrom(prime) =
        let start = 
            Seq.findIndex ((=) prime) primes
        
        if start < 0 then
            raise (NotPrimeException(prime, $"{prime} is not a prime number.") )
        else
            Seq.filter ((>=) prime) primes
            |> Seq.toArray
Imports System.Collections.Generic

<Serializable()> Public Class PrimeNumberGenerator
   Private Const START As Integer = 2
   Private maxUpperBound As Integer = 10000000
   Private upperBound As Integer
   Private primeTable() As Boolean
   Private primes As New List(Of Integer)

   Public Sub New(upperBound As Integer)
      If upperBound > maxUpperBound Then
         Dim message As String = String.Format(
             "{0} exceeds the maximum upper bound of {1}.",
             upperBound, maxUpperBound)
         Throw New ArgumentOutOfRangeException(message)
      End If
      Me.upperBound = upperBound
      ' Create array and mark 0, 1 as not prime (True).
      ReDim primeTable(upperBound)
      primeTable(0) = True
      primeTable(1) = True

      ' Use Sieve of Eratosthenes to determine prime numbers.
      For ctr As Integer = START To CInt(Math.Ceiling(Math.Sqrt(upperBound)))
         If primeTable(ctr) Then Continue For

         For multiplier As Integer = ctr To CInt(upperBound \ ctr)
            If ctr * multiplier <= upperBound Then primeTable(ctr * multiplier) = True
         Next
      Next
      ' Populate array with prime number information.
      Dim index As Integer = START
      Do While index <> -1
         index = Array.FindIndex(primeTable, index, Function(flag)
                                                       Return Not flag
                                                    End Function)
         If index >= 1 Then
            primes.Add(index)
            index += 1
         End If
      Loop
   End Sub

   Public Function GetAllPrimes() As Integer()
      Return primes.ToArray()
   End Function

   Public Function GetPrimesFrom(prime As Integer) As Integer()
      Dim start As Integer = primes.FindIndex(Function(value)
                                                 Return value = prime
                                              End Function)
      If start < 0 Then
         Throw New NotPrimeException(prime, String.Format("{0} is not a prime number.", prime))
      Else
         Return primes.FindAll(Function(value)
                                  Return value >= prime
                               End Function).ToArray()
      End If
   End Function
End Class

Aşağıdaki örnek, asal olmayan numaralarla yöntemine GetPrimesFrom iki çağrı yapar ve bunlardan biri uygulama etki alanı sınırlarını geçer. Her iki durumda da özel durum oluşturulur ve istemci kodunda başarıyla işlenir.

using System;
using System.Reflection;

class Example1
{
    public static void Main()
    {
        int limit = 10000000;
        PrimeNumberGenerator primes = new PrimeNumberGenerator(limit);
        int start = 1000001;
        try
        {
            int[] values = primes.GetPrimesFrom(start);
            Console.WriteLine($"There are {start} prime numbers from {limit} to {2}");
        }
        catch (NotPrimeException e)
        {
            Console.WriteLine($"{e.NonPrime} is not prime");
            Console.WriteLine(e);
            Console.WriteLine("--------");
        }

        AppDomain domain = AppDomain.CreateDomain("Domain2");
        PrimeNumberGenerator gen = (PrimeNumberGenerator)domain.CreateInstanceAndUnwrap(
                                          typeof(Example).Assembly.FullName,
                                          "PrimeNumberGenerator", true,
                                          BindingFlags.Default, null,
                                          new object[] { 1000000 }, null, null);
        try
        {
            start = 100;
            Console.WriteLine(gen.GetPrimesFrom(start));
        }
        catch (NotPrimeException e)
        {
            Console.WriteLine($"{e.NonPrime} is not prime");
            Console.WriteLine(e);
            Console.WriteLine("--------");
        }
    }
}
open System
open System.Reflection

let limit = 10000000
let primes = PrimeNumberGenerator limit
let start = 1000001
try
    let values = primes.GetPrimesFrom start
    printfn $"There are {values.Length} prime numbers from {start} to {limit}"
with :? NotPrimeException as e ->
    printfn $"{e.NonPrime} is not prime"
    printfn $"{e}"
    printfn "--------"

let domain = AppDomain.CreateDomain "Domain2"
let gen = 
    domain.CreateInstanceAndUnwrap(
        typeof<PrimeNumberGenerator>.Assembly.FullName,
        "PrimeNumberGenerator", true,
        BindingFlags.Default, null,
        [| box 1000000 |], null, null)
    :?> PrimeNumberGenerator
try
    let start = 100
    printfn $"{gen.GetPrimesFrom start}"
with :? NotPrimeException as e ->
    printfn $"{e.NonPrime} is not prime"
    printfn $"{e}"
    printfn "--------"
Imports System.Reflection

Module Example
   Sub Main()
      Dim limit As Integer = 10000000
      Dim primes As New PrimeNumberGenerator(limit)
      Dim start As Integer = 1000001
      Try
         Dim values() As Integer = primes.GetPrimesFrom(start)
         Console.WriteLine("There are {0} prime numbers from {1} to {2}",
                           start, limit)
      Catch e As NotPrimeException
         Console.WriteLine("{0} is not prime", e.NonPrime)
         Console.WriteLine(e)
         Console.WriteLine("--------")
      End Try

      Dim domain As AppDomain = AppDomain.CreateDomain("Domain2")
      Dim gen As PrimeNumberGenerator = domain.CreateInstanceAndUnwrap(
                                        GetType(Example).Assembly.FullName,
                                        "PrimeNumberGenerator", True,
                                        BindingFlags.Default, Nothing,
                                        {1000000}, Nothing, Nothing)
      Try
         start = 100
         Console.WriteLine(gen.GetPrimesFrom(start))
      Catch e As NotPrimeException
         Console.WriteLine("{0} is not prime", e.NonPrime)
         Console.WriteLine(e)
         Console.WriteLine("--------")
      End Try
   End Sub
End Module
' The example displays the following output:
'      1000001 is not prime
'      NotPrimeException: 1000001 is not a prime number.
'         at PrimeNumberGenerator.GetPrimesFrom(Int32 prime)
'         at Example.Main()
'      --------
'      100 is not prime
'      NotPrimeException: 100 is not a prime number.
'         at PrimeNumberGenerator.GetPrimesFrom(Int32 prime)
'         at Example.Main()
'      --------

Örnekler

Aşağıdaki örnek, catch hatalarını işlemek üzere tanımlanan bir with bloğunu gösterir (F#'ta ArithmeticException). Bu catch blok, DivideByZeroException hataları da yakalar, çünkü DivideByZeroException, ArithmeticException türetilir ve catch hataları için açıkça tanımlanmış bir DivideByZeroException blok yoktur.

using System;

class ExceptionTestClass
{
   public static void Main()
   {
      int x = 0;
      try
      {
         int y = 100 / x;
      }
      catch (ArithmeticException e)
      {
         Console.WriteLine($"ArithmeticException Handler: {e}");
      }
      catch (Exception e)
      {
         Console.WriteLine($"Generic Exception Handler: {e}");
      }
   }	
}
/*
This code example produces the following results:

ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
   at ExceptionTestClass.Main()

*/
module ExceptionTestModule

open System

let x = 0
try
    let y = 100 / x
    ()
with
| :? ArithmeticException as e ->
    printfn $"ArithmeticException Handler: {e}"
| e ->
    printfn $"Generic Exception Handler: {e}"

// This code example produces the following results:
//     ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
//        at <StartupCode$fs>.$ExceptionTestModule.main@()
Class ExceptionTestClass
   
   Public Shared Sub Main()
      Dim x As Integer = 0
      Try
         Dim y As Integer = 100 / x
      Catch e As ArithmeticException
         Console.WriteLine("ArithmeticException Handler: {0}", e.ToString())
      Catch e As Exception
         Console.WriteLine("Generic Exception Handler: {0}", e.ToString())
      End Try
   End Sub
End Class
'
'This code example produces the following results:
'
'ArithmeticException Handler: System.OverflowException: Arithmetic operation resulted in an overflow.
'   at ExceptionTestClass.Main()
'