Поделиться через


Создание и генерация исключений (Руководство по программированию C#)

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

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

  • Метод не способен выполнить свои определенные функции.

    Например, если значение параметры метода является недопустимым:

    static void CopyObject(SampleClass original)
    {
        if (original == null)
        {
            throw new System.ArgumentException("Parameter cannot be null", "original");
        }
    
    }
    
  • На основе состояния объекта выполнен неправильный вызов объекта.

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

    class ProgramLog
    {
        System.IO.FileStream logFile = null;
        void OpenLog(System.IO.FileInfo fileName, System.IO.FileMode mode) {}
    
        void WriteLog()
        {
            if (!this.logFile.CanWrite)
            {
                throw new System.InvalidOperationException("Logfile cannot be read-only");
            }
            // Else write data to the log and return.
        }
    }
    
  • Когда исключение вызывает аргумент метода.

    В этом случае, должно быть перехвачено исходное исключение и создан экземпляр ArgumentException. Исходное исключение должно быть передано конструктору ArgumentException в качестве параметра InnerException:

    static int GetValueFromArray(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch (System.IndexOutOfRangeException ex)
        {
            System.ArgumentException argEx = new System.ArgumentException("Index is out of range", "index", ex);
            throw argEx;
        }
    }
    

Исключения содержат свойство с именем StackTrace. Строка содержит имя методов в текущем стеке вызовов вместе с именем файла и номером строки, в которой было сгенерировано исключение для каждого метода. Объект StackTrace создается автоматически средой CLR из точки оператора throw, так что исключения должны генерироваться из той точки, где должна начинаться трассировка стека.

Все исключения содержат свойство с именем Message. Эта строка должно содержать сообщение с объяснением причин исключения. Обратите внимание, что секретные сведения не следует помещать в текст сообщения. Кроме Message, ArgumentException содержит свойство с именем ParamName, которому необходимо присвоить имя аргумента, вызвавшего генерацию исключения. В случае с установщиком свойств, свойству ParamName должно быть присвоено значение value.

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

Чего следует избегать при генерации исключений

Ниже приводятся рекомендации по тому, чего следует избегать при генерации исключений:

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

  • Исключения не должны возвращаться в качестве возвращаемого значения или параметра вместо генерации.

  • Не рекомендуется специально генерировать Exception, SystemException, NullReferenceException или IndexOutOfRangeException из собственного исходного кода.

  • Не рекомендуется создавать исключения, которые могут быть сгенерированы в режиме отладки, а не в режиме выпуска. Чтобы определить ошибки времени выполнения на этапе разработки, используйте Debug Assert.

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

Программы могут генерировать предопределенный класс исключений в пространстве имен System (если специально не обозначено иное), или создавать собственные классы исключений путем наследования от Exception. Производные классы должны определять, по меньшей мере, четыре конструктора: один конструктор по умолчанию, один конструктор, задающий свойство сообщения, и еще один, задающий свойства Message и InnerException. Четвертый конструктор служит для сериализации исключения. Новые классы исключений должны быть сериализуемыми. Примеры.

[Serializable()]
public class InvalidDepartmentException : System.Exception
{
    public InvalidDepartmentException() : base() { }
    public InvalidDepartmentException(string message) : base(message) { }
    public InvalidDepartmentException(string message, System.Exception inner) : base(message, inner) { }

    // A constructor is needed for serialization when an 
    // exception propagates from a remoting server to the client.  
    protected InvalidDepartmentException(System.Runtime.Serialization.SerializationInfo info,
        System.Runtime.Serialization.StreamingContext context) { }
}

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

Спецификация языка C#

Дополнительные сведения см. в Спецификация языка C#. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.

См. также

Ссылки

Исключения и обработка исключений (Руководство по программированию в C#)

Обработка исключений (Руководство по программированию на C#)

Основные понятия

Руководство по программированию на C#

Иерархия исключений