Exception Класс

Определение

Представляет ошибки, которые происходят во время выполнения приложения.

public ref class Exception
public ref class Exception : System::Runtime::Serialization::ISerializable
public ref class Exception : System::Runtime::InteropServices::_Exception, System::Runtime::Serialization::ISerializable
public class Exception
public class Exception : System.Runtime.Serialization.ISerializable
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDual)]
[System.Serializable]
public class Exception : System.Runtime.Serialization.ISerializable
[System.Serializable]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public class Exception : System.Runtime.InteropServices._Exception, System.Runtime.Serialization.ISerializable
[System.Serializable]
[System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
[System.Runtime.InteropServices.ComVisible(true)]
public class Exception : System.Runtime.Serialization.ISerializable
type Exception = class
type Exception = class
    interface ISerializable
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDual)>]
[<System.Serializable>]
type Exception = class
    interface ISerializable
[<System.Serializable>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Exception = class
    interface ISerializable
    interface _Exception
[<System.Serializable>]
[<System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type Exception = class
    interface ISerializable
Public Class Exception
Public Class Exception
Implements ISerializable
Public Class Exception
Implements _Exception, ISerializable
Наследование
Exception
Производный
Атрибуты
Реализации

Примеры

В следующем примере показан catch блок, определенный для обработки ArithmeticException ошибок. Этот catch блок также перехватывает DivideByZeroException ошибки, так как DivideByZeroException является производным от ArithmeticException и не существует блока, catch явно определенного для DivideByZeroException ошибок.

using namespace System;
int main()
{
    int x = 0;
    try
    {
        int y = 100 / x;
    }
    catch ( ArithmeticException^ e ) 
    {
        Console::WriteLine( "ArithmeticException Handler: {0}", e );
    }
    catch ( Exception^ e ) 
    {
        Console::WriteLine( "Generic Exception Handler: {0}", e );
    }
}
/*
This code example produces the following results:

ArithmeticException Handler: System.DivideByZeroException: Attempted to divide by zero.
   at main()
 
*/
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()

*/
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()
'

Комментарии

Этот класс является базовым классом для всех исключений. При возникновении ошибки система или выполняемое в настоящее время приложение сообщает о нем, вызывая исключение, которое содержит сведения об ошибке. После возникновения исключения оно обрабатывается приложением или обработчиком исключений по умолчанию.

Содержание

Ошибки и исключения
Блоки try/catch
Функции типов исключений
Свойства класса Exception
Вопросы производительности
Повторное создание исключения
Выбор стандартных исключений
Реализация пользовательских исключений

Ошибки и исключения

Ошибки времени выполнения могут возникать по разным причинам. Однако не все ошибки должны обрабатываться как исключения в коде. Ниже приведены некоторые категории ошибок, которые могут возникать во время выполнения, и соответствующие способы реагирования на них.

  • Ошибки использования. Ошибка использования представляет ошибку в логике программы, которая может привести к исключению. Однако эта ошибка должна быть решена не посредством обработки исключений, но путем изменения неисправного кода. Например, переопределение Object.Equals(Object) метода в следующем примере предполагает, что obj аргумент всегда должен иметь значение, отличное от NULL.

    using System;
    
    public class Person
    {
       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.
          Person p = (Person) obj;
          return this.Name.Equals(p.Name);
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person p1 = new Person();
          p1.Name = "John";
          Person p2 = null;
    
          // The following throws a NullReferenceException.
          Console.WriteLine("p1 = p2: {0}", 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 Example
       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
    

    NullReferenceExceptionИсключение, которое возникает, obj Если null можно устранить, изменив исходный код, чтобы явно проверить наличие значения null перед вызовом Object.Equals переопределения, а затем повторной компиляцией. В следующем примере содержится исправленный исходный код, обрабатывающий null аргумент.

    using System;
    
    public class Person
    {
       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.
           Person p = obj as Person;
           if (p == null)
              return false;
           else
              return this.Name.Equals(p.Name);
       }
    }
    
    public class Example
    {
       public static void Main()
       {
          Person p1 = new Person();
          p1.Name = "John";
          Person p2 = null;
    
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
       }
    }
    // The example displays the following output:
    //        p1 = p2: False
    
    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 handles a null obj argument.
          Dim p As Person = TryCast(obj, Person)
          If p Is Nothing Then 
             Return False
          Else
             Return Me.Name.Equals(p.Name)
          End If
       End Function
    End Class
    
    Module Example
       Public Sub Main()
          Dim p1 As New Person()
          p1.Name = "John"
          Dim p2 As Person = Nothing
          
          Console.WriteLine("p1 = p2: {0}", p1.Equals(p2))   
       End Sub
    End Module
    ' The example displays the following output:
    '       p1 = p2: False
    

    Вместо использования обработки исключений для ошибок использования можно использовать Debug.Assert метод для обнаружения ошибок использования в отладочных сборках и Trace.Assert метод для обнаружения ошибок использования в сборках отладки и выпуска. Дополнительные сведения см. в разделе Утверждения в управляемом коде.

  • Ошибки программы. Ошибка программы — это ошибка во время выполнения, которую не всегда можно избежать путем написания кода без ошибок.

    В некоторых случаях ошибка программы может отражать ожидаемое или предполагаемое состояние ошибки. В этом случае может потребоваться избежать использования обработки исключений для устранения ошибок программы, а затем повторить операцию. Например, если пользователь должен ввести дату в определенном формате, можно выполнить синтаксический анализ строки даты, вызвав DateTime.TryParseExact метод, который возвращает Boolean значение, указывающее, была ли операция анализа успешной, вместо использования DateTime.ParseExact метода, который создает FormatException исключение, если строка даты не может быть преобразована в DateTime значение. Аналогично, если пользователь пытается открыть несуществующий файл, можно сначала вызвать File.Exists метод, чтобы проверить, существует ли файл, и, если он не будет, запрашивать у пользователя, нужно ли его создать.

    В других случаях ошибка программы отражает непредвиденное условие ошибки, которое может быть обработано в коде. Например, даже если проверено, что файл существует, он может быть удален до его открытия или поврежден. В этом случае попытка открыть файл путем создания экземпляра StreamReader объекта или вызова Open метода может вызвать FileNotFoundException исключение. В таких случаях для восстановления после ошибки следует использовать обработку исключений.

  • Сбои системы. Сбой системы — это ошибка времени выполнения, которая не может быть обработана программно понятным образом. Например, любой метод может вызвать исключение, OutOfMemoryException Если среда CLR не может выделить дополнительную память. Обычно системные сбои не обрабатываются с помощью обработки исключений. Вместо этого можно использовать событие, например, AppDomain.UnhandledException и вызвать Environment.FailFast метод для регистрации сведений об исключениях и уведомить пользователя об ошибке до завершения работы приложения.

Блоки try/catch

Среда CLR предоставляет модель обработки исключений, основанную на представлении исключений в виде объектов, а также разделении кода программы и кода обработки исключений на try блоки и catch блоки. Может существовать один или несколько catch блоков, каждый из которых предназначен для обработки определенного типа исключений, или один блок, предназначенный для перехвата более конкретного исключения, чем у другого блока.

Если приложение обрабатывает исключения, происходящие во время выполнения блока кода приложения, код должен быть помещен в try оператор и называться try блоком. Код приложения, обрабатывающий исключения, созданные try блоком, помещается в catch оператор и называется catch блоком. catchС блоком связано ноль или более блоков try , и каждый catch блок включает фильтр типа, который определяет типы исключений, которые он обрабатывает.

Когда в блоке возникает исключение try , система ищет связанные catch блоки в том порядке, в котором они отображаются в коде приложения, пока не обнаружит catch блок, обрабатывающий исключение. catchБлок обрабатывает исключение типа T , если фильтр типа блока catch указывает T или любой тип, T производный от. Система прекратит поиск после того, как обнаружит первый catch блок, обрабатывающий исключение. По этой причине в коде приложения catch блок, обрабатывающий тип, должен быть указан перед catch блоком, обрабатывающим его базовые типы, как показано в примере, который следует за этим разделом. Блок catch, дескрипторы которого System.Exception указаны последними.

Если ни один из catch блоков, связанных с текущим try блоком, не обрабатывает исключение, а текущий try блок вложен в другие try блоки в текущем вызове, catch Поиск осуществляется по блокам, связанным со следующим включающим try блоком. Если catch блок для исключения не найден, система выполняет поиск предыдущего уровня вложенности в текущем вызове. Если catch в текущем вызове не найдено ни одного блока для исключения, исключение передается вверх по стеку вызовов, а в предыдущем кадре стека выполняется поиск catch блока, обрабатывающего исключение. Поиск в стеке вызовов продолжится до тех пор, пока не будет обработано исключение или пока в стеке вызовов не будут существовать кадры. Если начало стека вызовов достигается без поиска catch блока, обрабатывающего исключение, обработчик исключений по умолчанию обрабатывает его и завершает работу приложения.

Функции типов исключений

Типы исключений поддерживают следующие функции.

  • Понятный для человека текст, описывающий ошибку. При возникновении исключения среда выполнения предоставляет доступ к текстовому сообщению для информирования пользователя о характере ошибки и предложения действия для решения проблемы. Это текстовое сообщение хранится в Message свойстве объекта исключения. Во время создания объекта исключения можно передать в конструктор текстовую строку для описания сведений об этом конкретном исключении. Если для конструктора не задан аргумент сообщения об ошибке, используется сообщение об ошибке по умолчанию. Дополнительные сведения см. в описании свойства Message.

  • Состояние стека вызовов при возникновении исключения. StackTraceСвойство содержит трассировку стека, которую можно использовать для определения места возникновения ошибки в коде. В трассировке стека перечислены все вызываемые методы и номера строк в исходном файле, где выполняются вызовы.

Свойства класса Exception

ExceptionКласс включает ряд свойств, помогающих определить расположение кода, тип, файл справки и причину исключения: StackTrace , InnerException , Message , HelpLink ,, HResult Source , TargetSite и Data .

Если между двумя или более исключениями существует связь с причинами, InnerException это свойство поддерживает эти сведения. Внешнее исключение создается в ответ на это внутреннее исключение. Код, обрабатывающий внешнее исключение, может использовать сведения из предыдущего внутреннего исключения для более адекватной обработки ошибки. Дополнительные сведения об исключении могут храниться в виде коллекции пар "ключ-значение" в Data свойстве.

Строка сообщения об ошибке, которая передается конструктору во время создания объекта исключения, должна быть локализована и может быть предоставлена из файла ресурсов с помощью ResourceManager класса. Дополнительные сведения о локализованных ресурсах см. в разделах Создание вспомогательных сборок и Упаковка и развертывание ресурсов .

Чтобы предоставить пользователю подробные сведения о причине возникновения исключения, HelpLink свойство может содержать URL-адрес (или URN) файла справки.

ExceptionКласс использует COR_E_EXCEPTION HRESULT, имеющий значение 0x80131500.

Список начальных значений свойств для экземпляра Exception класса см. в разделе Exception конструкторы.

Вопросы производительности

Создание или обработка исключения требует значительного количества системных ресурсов и времени выполнения. Вызывайте исключения только для обработки действительно неисключительных условий, а не для обработки прогнозируемых событий или управления потоком. Например, в некоторых случаях, например при разработке библиотеки классов, разумно создать исключение, если аргумент метода является недопустимым, так как предполагается, что метод будет вызываться с допустимыми параметрами. Недопустимый аргумент метода, если он не является результатом ошибки использования, означает, что возникла непредвиденная ошибка. И наоборот, не вызывайте исключение, если ввод пользователя является недопустимым, так как вы можете рассчитывать, что пользователи иногда вводят недопустимые данные. Вместо этого предоставьте механизм повторных попыток, чтобы пользователи могли ввести допустимые входные данные. Кроме того, не следует использовать исключения для обработки ошибок использования. Вместо этого используйте утверждения для обнаружения и исправления ошибок использования.

Кроме того, не вызывайте исключение, если достаточно кода возврата; не преобразуйте код возврата в исключение; и не перехватывают исключение, игнорируйте его, а затем продолжайте обработку.

Повторный вызов исключения

Во многих случаях обработчик исключений просто хочет передать исключение в вызывающий объект. Чаще всего это происходит в следующих случаях.

  • библиотека классов, которая, в свою очередь, заключает вызовы методов в библиотеку классов платформа .NET Framework или другие библиотеки классов.

  • Приложение или библиотека, вызывающая неустранимое исключение. Обработчик исключений может зарегистрировать исключение, а затем повторно создать исключение.

для повторного создания исключения рекомендуется просто использовать инструкцию throw в C# и инструкцию throw в Visual Basic без включения выражения. Это гарантирует, что все сведения стека вызовов сохраняются при распространении исключения вызывающему объекту. Это показано в следующем примере. Метод расширения строки ( FindOccurrences ) заключает в оболочку один или несколько вызовов String.IndexOf(String, Int32) без проверки своих аргументов заранее.

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

public static class Library
{
   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 e) {
         // Perform some action here, such as logging this exception.

         throw;
      }
      return indexes.ToArray();
   }
}
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices

Public Module Library
   <Extension()>
   Public Function FindOccurrences(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

Затем вызывающий объект вызывается FindOccurrences дважды. Во втором вызове FindOccurrences вызывающий объект передает в null качестве строки поиска, что приводит к String.IndexOf(String, Int32) созданию ArgumentNullException исключения методом. Это исключение обрабатывается FindOccurrences методом и передается обратно вызывающему объекту. Поскольку оператор throw используется без выражения, выходные данные в примере показывают, что стек вызовов сохранен.

public class Example
{
   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 ({0}) occurred.",
                           e.GetType().Name);
         Console.WriteLine("Message:\n   {0}\n", e.Message);
         Console.WriteLine("Stack Trace:\n   {0}\n", e.StackTrace);
      }
   }

   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()
Module Example
   Public Sub Main()
      Dim s As String = "It was a cold day when..."
      Dim indexes() As Integer = s.FindOccurrences("a")
      ShowOccurrences(s, "a", indexes)
      Console.WriteLine()

      Dim toFind As String = Nothing
      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:{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()

Напротив, если исключение создается повторно с помощью метода

throw e;
Throw e  

, полный стек вызовов не сохраняется, и в примере создается следующий результат:

'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()  

Немного более громоздкий альтернативой является вызов нового исключения и сохранение сведений стека вызовов исходного исключения во внутреннем исключении. Затем вызывающий объект может использовать свойство нового исключения InnerException для получения кадра стека и других сведений об исходном исключении. В этом случае оператор Throw будет следующим:

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

Пользовательский код, обрабатывающий исключение, должен иметь представление о том, что InnerException свойство содержит сведения об исходном исключении, как показано в следующем обработчике исключений.

try {
   indexes = s.FindOccurrences(toFind);
   ShowOccurrences(s, toFind, indexes);
}
catch (ArgumentNullException e) {
   Console.WriteLine("An exception ({0}) occurred.",
                     e.GetType().Name);
   Console.WriteLine("   Message:\n{0}", e.Message);
   Console.WriteLine("   Stack Trace:\n   {0}", e.StackTrace);
   Exception ie = e.InnerException;
   if (ie != null) {
      Console.WriteLine("   The Inner Exception:");
      Console.WriteLine("      Exception Name: {0}", ie.GetType().Name);
      Console.WriteLine("      Message: {0}\n", ie.Message);
      Console.WriteLine("      Stack Trace:\n   {0}\n", ie.StackTrace);
   }
}
// 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)

Выбор стандартных исключений

если необходимо создать исключение, часто можно использовать существующий тип исключения в платформа .NET Framework вместо реализации пользовательского исключения. В этих двух условиях следует использовать стандартный тип исключений.

  • Создается исключение, вызванное ошибкой использования (то есть ошибкой в логике программы, выполняемой разработчиком, вызывающим метод). Как правило, создается исключение, например,, ArgumentException ArgumentNullException InvalidOperationException или NotSupportedException . Строка, предоставляемая конструктору объекта исключения при создании объекта исключения, должна описывать ошибку, чтобы разработчик мог ее исправить. Дополнительные сведения см. в описании свойства Message.

  • вы обрабатываете ошибку, которая может быть передана вызывающему объекту с существующим исключением платформа .NET Framework. Рекомендуется создавать наиболее производное исключение. Например, если метод требует, чтобы аргумент был допустимым членом типа перечисления, следует вызвать исключение InvalidEnumArgumentException (самый производный класс), а не ArgumentException .

В следующей таблице перечислены распространенные типы исключений и условия их создания.

Исключение Условие
ArgumentException Непустой аргумент, передаваемый в метод, является недопустимым.
ArgumentNullException Аргумент, передаваемый в метод, — null .
ArgumentOutOfRangeException Аргумент находится за пределами диапазона допустимых значений.
DirectoryNotFoundException Недопустимая часть пути к каталогу.
DivideByZeroException Знаменатель в операции деления или целого числа Decimal равен нулю.
DriveNotFoundException Диск недоступен или не существует.
FileNotFoundException Файл не существует.
FormatException Значение не находится в соответствующем формате для преобразования из строки методом преобразования, например Parse .
IndexOutOfRangeException Индекс находится за пределами границ массива или коллекции.
InvalidOperationException Вызов метода недопустим в текущем состоянии объекта.
KeyNotFoundException Не удается найти указанный ключ для доступа к элементу в коллекции.
NotImplementedException Метод или операция не реализованы.
NotSupportedException Метод или операция не поддерживается.
ObjectDisposedException Операция выполняется над объектом, который был ликвидирован.
OverflowException Арифметическое, приведение или операция преобразования приводят к переполнению.
PathTooLongException Длина пути или имени файла превышает максимальную длину, определенную системой.
PlatformNotSupportedException Операция не поддерживается на текущей платформе.
RankException В метод передается массив с неправильным числом измерений.
TimeoutException Срок действия интервала времени, выделенного для операции, истек.
UriFormatException Используется недопустимый универсальный код ресурса (URI).

Реализация пользовательских исключений

в следующих случаях использование существующего исключения платформа .NET Framework для обработки состояния ошибки неадекватно:

  • если исключение отражает уникальную ошибку программы, которая не может быть сопоставлена с существующим исключением платформа .NET Framework.

  • если для исключения требуется обработка, которая отличается от обработки, подходящей для существующего исключения платформа .NET Framework, или исключение должно быть неоднозначной из аналогичного исключения. Например, если при ArgumentOutOfRangeException синтаксическом анализе числового представления строки, находящейся за пределами диапазона целевого целочисленного типа, выдается исключение, то не нужно использовать то же исключение для ошибки, полученной от вызывающей стороны, не предоставляющей соответствующие значения с ограничениями при вызове метода.

Exceptionкласс является базовым классом всех исключений в платформа .NET Framework. Многие производные классы основываются на наследуемом поведении членов Exception класса; они не переопределяют члены Exception , а также не определяют уникальные члены.

Определение собственного класса исключений:

  1. Определите класс, наследующий от Exception . При необходимости определите все уникальные элементы, необходимые для класса, чтобы предоставить дополнительные сведения об исключении. Например, ArgumentException класс включает ParamName свойство, указывающее имя параметра, аргумент которого вызывал исключение, а RegexMatchTimeoutException свойство содержит MatchTimeout свойство, указывающее интервал времени ожидания.

  2. При необходимости переопределите все унаследованные члены, функциональность которых требуется изменить или изменить. Обратите внимание, что большинство существующих производных классов Exception не переопределяют поведение наследуемых членов.

  3. Определите, является ли пользовательский объект исключения сериализуемым. Сериализация позволяет сохранять сведения об исключении и позволяет совместно использовать данные исключений сервером и прокси клиента в контексте удаленного взаимодействия. Чтобы сделать объект исключения сериализуемым, пометьте его SerializableAttribute атрибутом.

  4. Определите конструкторы класса исключений. Как правило, классы исключений имеют один или несколько следующих конструкторов:

    • Exception(), который использует значения по умолчанию для инициализации свойств нового объекта исключения.

    • Exception(String), который инициализирует новый объект исключения с указанным сообщением об ошибке.

    • Exception(String, Exception), который инициализирует новый объект исключения с указанным сообщением об ошибке и внутренним исключением.

    • Exception(SerializationInfo, StreamingContext)— Это protected конструктор, инициализирующий новый объект исключения из сериализованных данных. Этот конструктор следует реализовать, если вы решили сделать объект исключения сериализуемым.

В следующем примере показано использование класса пользовательского исключения. Он определяет NotPrimeException исключение, которое создается, когда клиент пытается получить последовательность простых чисел, указав начальный номер, который не является простым. Исключение определяет новое свойство, NonPrime которое возвращает непростое число, которое привело к исключению. Помимо реализации защищенного конструктора без параметров и конструктора с SerializationInfo параметрами и StreamingContext для сериализации, NotPrimeException класс определяет три дополнительных конструктора для поддержки NonPrime Свойства. Каждый конструктор вызывает конструктор базового класса, а также сохраняет значение непростого числа. NotPrimeExceptionКласс также помечается SerializableAttribute атрибутом.

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; } }
}
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Класс, показанный в следующем примере, использует Сиеве из ератоссенес для вычисления последовательности простых чисел из 2 в предел, заданный клиентом при вызове его конструктора класса. GetPrimesFromМетод возвращает все простые числа, которые больше или равны указанному нижнему пределу, но выдает исключение, NotPrimeException Если нижний предел не является простым числом.

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();
   }
}
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

В следующем примере выполняется два вызова GetPrimesFrom метода с непростыми числами, один из которых пересекают границы домена приложения. В обоих случаях исключение вызывается и успешно обрабатывается в клиентском коде.

using System;
using System.Reflection;

class Example
{
   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 {0} prime numbers from {1} to {2}",
                           start, limit);
      }
      catch (NotPrimeException e)
      {
         Console.WriteLine("{0} is not prime", e.NonPrime);
         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("{0} is not prime", e.NonPrime);
         Console.WriteLine(e);
         Console.WriteLine("--------");
      }
   }
}
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()
'      --------

Windows Runtime и платформа .NET Framework 4.5.1

в .net для приложений магазина Windows 8. x для Windows 8 некоторые сведения об исключении обычно теряются, если исключение распространяется через кадры стека, отличные от платформа .NET Framework. начиная с платформа .NET Framework 4.5.1 и Windows 8.1, среда clr по-своему использует исходный Exception объект, который был создан, если это исключение не было изменено в кадре стека, не относящемся к платформа .NET Framework.

Конструкторы

Exception()

Инициализирует новый экземпляр класса Exception.

Exception(SerializationInfo, StreamingContext)

Инициализирует новый экземпляр класса Exception с сериализованными данными.

Exception(String)

Инициализирует новый экземпляр класса Exception с указанным сообщением об ошибке.

Exception(String, Exception)

Инициализирует новый экземпляр класса Exception указанным сообщением об ошибке и ссылкой на внутреннее исключение, вызвавшее данное исключение.

Свойства

Data

Возвращает коллекцию пар «ключ-значение», предоставляющую дополнительные сведения об исключении.

HelpLink

Получает или задает ссылку на файл справки, связанный с этим исключением.

HResult

Возвращает или задает HRESULT — кодированное числовое значение, присвоенное определенному исключению.

InnerException

Возвращает экземпляр класса Exception, который вызвал текущее исключение.

Message

Возвращает сообщение, описывающее текущее исключение.

Source

Возвращает или задает имя приложения или объекта, вызывавшего ошибку.

StackTrace

Получает строковое представление непосредственных кадров в стеке вызова.

TargetSite

Возвращает метод, создавший текущее исключение.

Методы

Equals(Object)

Определяет, равен ли указанный объект текущему объекту.

(Унаследовано от Object)
GetBaseException()

При переопределении в производном классе возвращает исключение Exception, которое является первопричиной одного или нескольких последующих исключений.

GetHashCode()

Служит хэш-функцией по умолчанию.

(Унаследовано от Object)
GetObjectData(SerializationInfo, StreamingContext)

При переопределении в производном классе задает объект SerializationInfo со сведениями об исключении.

GetType()

Возвращает тип среды выполнения текущего экземпляра.

GetType()

Возвращает объект Type для текущего экземпляра.

(Унаследовано от Object)
MemberwiseClone()

Создает неполную копию текущего объекта Object.

(Унаследовано от Object)
ToString()

Создает и возвращает строковое представление текущего исключения.

События

SerializeObjectState
Является устаревшей.

Возникает, когда исключение сериализовано для создания объекта состояния исключения, содержащего сериализованные данные об исключении.

Применяется к

См. также раздел