Исключение с нулевым сообщением - PullRequest
3 голосов
/ 15 декабря 2011

Я обнаружил, что сообщение об исключении не может быть пустым в C #, и после попытки этого

 var ex = new Exception(null);
 Console.WriteLine(ex.Message);

Я получаю следующее сообщение:

Исключение типа 'System.Exception' было сгенерировано.

Но в этом случае

 var ex = new Exception(string.Empty);
 Console.WriteLine(ex.Message);

сообщение просто пустое.

Как это можно объяснить? Как вы думаете, это ожидаемое поведение?

Ответы [ 4 ]

5 голосов
/ 15 декабря 2011

Другие ответы (не включая ответ Чопикадзе), похоже, основаны на неправильном прочтении фактов.Ни один из примеров не генерирует исключение.

Скорее, в первом примере созданное исключение ex предоставляет сообщение, поскольку значение параметра сообщения конструктора было нулевым.Сообщение является «исключением типа« System.Exception »было сгенерировано».

Это довольно распространенная практика - иметь некоторый запасной вариант поведения, когда ссылка на объект является нулевой, так что это «как это можно объяснить».«Ожидаемое», конечно, зависит от ваших ожиданий.

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

РЕДАКТИРОВАТЬ

Поведение также задокументировано в примечания к свойству Message : «Если в конструктор для текущего экземпляра не было отправлено сообщение, система предоставит сообщение по умолчанию, отформатированное с использованием текущей системной культуры.»

Я посмотрелв спецификации CLI и в спецификации C #, и я не нашел упоминания о требовании, чтобы Message имел ненулевое возвращаемое значение, поэтому я предполагаю, что это поддерживает представление о том, что это поведение является решением при разработке структуры.

3 голосов
/ 15 декабря 2011

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

internal string _message;

public Exception(string message)
{
    this.Init();
    this._message = message;
}


private void Init()
{
    this._message = null;
    this._stackTrace = null;
    this._dynamicMethods = null;
    this.HResult = -2146233088;
    this._xcode = -532462766;
    this._xptrs = IntPtr.Zero;
    this._watsonBuckets = null;
    this._ipForWatsonBuckets = UIntPtr.Zero;
    this._safeSerializationManager = new SafeSerializationManager();
}

public virtual string Message
{
    [SecuritySafeCritical]
    get
    {
        if (this._message != null)
        {
            return this._message;
        }
        if (this._className == null)
        {
            this._className = this.GetClassName();
        }
        return Environment.GetRuntimeResourceString("Exception_WasThrown", new object[] { this._className });
    }
}

Так что, если вы используете null в качестве сообщения в конструкторе, выдается локализованная строка типа «Исключение типа System.Exception». будет использоваться в качестве сообщения. Это означает - ваше Исключение по-прежнему существует, а не другое, но его свойство Message возвращает другое (вычисленное) значение вместо нулевого значения из конструктора.

Я думаю, что согласно проекту (и, возможно, используется в других местах), Exception.Message всегда должно быть не нулевым. Поэтому, если мы хотим разрешить разработчикам использовать конструктор по умолчанию для класса Exception (например, для использования с отражением или для разрешения заполнения свойств позже), но мы также хотим, чтобы Message всегда был не нулевым - мы должны обернуть Message чем-нибудь. Я думаю, что одним из возможных мест использования сообщений является диалоговое окно по умолчанию, отображаемое после возникновения исключения. Таким образом, вместо проверки можно использовать только свойство сообщения - свойство сообщения равно нулю и т. Д.

2 голосов
/ 15 декабря 2011

string.Empty не равно нулю, это константа для "".

Ваш первый пример дает сообщение по умолчанию, второй пример - пустая строка

0 голосов
/ 15 декабря 2011

Да, используемый вами конструктор требует строку. String.Empty - это не то же самое, что null, поэтому он выдаст исключение.

http://msdn.microsoft.com/en-us/library/system.exception.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...