2011-12-15 3 views
3

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

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

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

исключения типа «System.Exception ' был брошен.

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

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

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

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

+1

Отметьте ctor «Исключение» с помощью .NET Reflector или Telerik JustDecompile :) – kol

ответ

4

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

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

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

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

EDIT

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

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

+0

Я попытался изменить «тестовый» код на: var ex = new NotSupportedException (null); После того, как это сообщение будет изменено на «Исключение типа« System.NotSupportedException »было брошено». Таким образом, похоже, что это поведение не используется для того, чтобы показать, что вы передаете null в конструктор Exception. – chopikadze

+0

В сообщении будет показан фактический тип исключения. См. Отредактированный ответ для более подробной информации, и ответ Чопикадзе для реализации. – phoog

2

string.Empty не является нулевой константой для "".

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

+3

Первый пример: * not * производя исключение нулевой ссылки; построенное исключение 'ex' предоставляет сообщение, потому что параметр сообщения имеет значение null, поэтому вызов' ex.Message' возвращает строку «исключение типа« System.Exception »было выбрано». – phoog

+0

Да, который обертывает нулевую ссылку, потому что он пытается записать пустую строку в консоль .... – Maess

+0

Console.WriteLine ((string) null); не выбрасывает исключение. Нет нового исключения, свойство Message просто возвращает другую строку вместо нуля – chopikadze

1

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

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

+0

Он не бросит исключение. Создайте проект для консольного приложения, скопируйте/вставьте код и используйте отладчик. Исключений нет! – chopikadze

+0

Как сказано, он не генерирует исключение, он присваивает эту строку tom Message –

3

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

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

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

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

+0

Согласен @chopikadze, вы объясните, как это работает, но для меня это странно ... –

+0

@ArsenMkrt Ответ обновлен – chopikadze

+1

Старый материал, но Exception.Message вполне может быть пустым на практике. Попробуйте throw new System.Web.UI.ViewStateException(); например. – philw

Смежные вопросы