C# 带有空消息的异常

C# 带有空消息的异常,c#,exception,C#,Exception,我发现异常消息在C#中不能为null,在尝试了这个之后 var ex = new Exception(null); Console.WriteLine(ex.Message); 我得到以下信息: 引发了类型为“System.Exception”的异常 但是在这种情况下, var ex = new Exception(string.Empty); Console.WriteLine(ex.Message); 消息是空的 如何解释这一点?你认为这是预期的行为吗 string.Empty不

我发现异常消息在C#中不能为null,在尝试了这个之后

 var ex = new Exception(null);
 Console.WriteLine(ex.Message);
我得到以下信息:

引发了类型为“System.Exception”的异常

但是在这种情况下,

 var ex = new Exception(string.Empty);
 Console.WriteLine(ex.Message);
消息是空的


如何解释这一点?你认为这是预期的行为吗

string.Empty
不为null它是
的常量


第一个示例给出了一条默认消息,第二个示例是一个空字符串

是的,您使用的构造函数需要一个字符串。String.Empty与null不同,因此它将引发异常

其他答案(不包括chopikadze的答案)似乎是基于对事实的误读。两个示例都没有引发异常

相反,在第一个示例中,构造的异常
ex
提供了一条消息,因为构造函数的消息参数的值为null。消息为“引发了类型为“System.exception”的异常”

当对象引用为null时,有一些回退行为是一种相当常见的做法,所以这就是“如何解释它”。当然,它是否是“预期的”,取决于你的预期

在处理异常的过程中抛出异常可能会有问题,因此框架设计者必须选择这种行为来减少这种可能性。坦率地说,如果我们都必须考虑异常消息可能为空的可能性,那将是一场噩梦

编辑

该行为还记录在:“如果未向当前实例的构造函数提供任何消息,系统将提供使用当前系统区域性格式化的默认消息。”


我查看了CLI规范和C#规范,没有发现要求消息具有非null返回值的内容,因此我猜这支持这样的观点,即这种行为是一种框架设计决策。

实际上构造函数不需要字符串,您绝对可以使用null。这是异常类的反射部分:

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'的异常”的本地化字符串将用作消息。这意味着-仍然存在异常,而不是另一个异常,但它的属性消息从构造函数返回另一个(计算的)值,而不是null


我认为它是由设计定义的(可能在其他地方也有使用)异常。消息应该始终不为null。所以,如果我们希望允许开发人员对异常类使用默认构造函数(例如,用于反射或允许以后填充属性),但我们也希望消息始终不为null,那么我们应该用一些东西包装消息。我认为,消息使用的一个可能位置是异常发生后显示的默认对话框。通过这种方式,可以只使用消息属性,而不是检查-消息属性是否等于null等。

使用.NET Reflector或Telerik JustDecompile检查
异常的ctor:)第一个示例没有生成null引用异常;构造的异常
ex
提供了一条消息,因为消息参数为null,所以对
ex.message
的调用返回字符串“System.exception”类型的异常被抛出。是的,它正在包装一个null引用,因为他正试图将null字符串写入console…console.WriteLine((字符串)无效);不会抛出异常。并没有新的异常,Message属性只返回另一个字符串,而不是nullno@Maess,它将“类型为'System.exception'was shown'的异常”分配给消息,而消息不是expected@Maess否:如果存在空引用,代码将引发NullReferenceException。那是不会发生的。相反,消息“抛出类型为'System.Exception'的异常。”正在写入控制台。顺便说一句,我没有否决你的答案。它不会引发例外。为控制台应用程序创建项目,复制/粘贴代码,并使用调试器。没有例外!如上所述,它不会抛出它分配给tom MessageI试图将“测试”代码更改为以下字符串的异常:var ex=new NotSupportedException(null);将此消息更改为“引发了类型为“System.NotSupportedException”的异常”后。因此,此行为似乎不用于显示将null传递给异常的构造函数。此消息将显示异常的实际类型。有关更多详细信息,请参见编辑后的答案,以及chopikadze关于实现的答案。旧的东西,但异常。消息在实践中很可能为空。尝试抛出新的System.Web.UI.ViewStateException();例如