70

在下面的代码中,为什么两个string.Format调用的行为方式不同?在第一个中,没有抛出异常,但在第二个ArgumentNullException中抛出 an。

static void Main(string[] args)
{
    Exception e = null;
    string msgOne = string.Format("An exception occurred: {0}", e);
    string msgTwo = string.Format("Another exception occurred: {0}", null);
}

有人可以帮我理解两者之间的区别吗?

4

5 回答 5

56

我在这里猜测,但这看起来是您正在打哪个重载呼叫的区别; String.Format有多个。

在第一个示例中,您击中String.Format(string,object).

在第二个示例中,通过提供null您最有可能达到String.Format(string,params object[])哪个,根据文档,会引发一个ArgumentNullException何时:

格式或参数为空。

如果您正在运行 .NET4,请尝试使用命名参数:

String.Format("Another exception occured: {0}", arg0: null);

为什么会遇到params object[]超载?可能是因为null它不是一个对象,并且params工作方式是您可以在调用中将每个值作为新对象传递,或者其传递给一个值数组。也就是说,以下是同一个

String.Format("Hello, {0}! Today is {1}.", "World", "Sunny");
String.Format("Hello, {0}! Today is {1}.", new Object[]{ "World", "Sunny" })

因此,它将您的声明调用转换为以下内容:

String format = "Another exception occured: {0}";
Object[] args = null;
String.Format(format, args); // throw new ArgumentNullException();
于 2012-11-07T19:11:54.540 回答
12

在您的第一个示例中,您正在点击Format(String, Object),反汇编时看起来像这样:

 public static string Format(string format, object arg0)
 {
    return Format(null, format, new object[] { arg0 });
 }

注意new object[]周围。

第二个,您显然正在Format(string, object[])使用,至少这是我执行相同测试时调用的那个。拆开看是这样的:

 public static string Format(string format, params object[] args)
 {
     return Format(null, format, args);
 }

所以所有这些实际上都被汇集到Format(IFormatProvider, string, object[]). 很酷,让我们看看那里的前几行:

public static string Format(IFormatProvider provider, string format, params object[] args)
{
    if ((format == null) || (args == null))
    {
        throw new ArgumentNullException((format == null) ? "format" : "args");
    }
...
}

...welp,这就是你的问题,就在那里!第一次调用是将其包装在一个新数组中,因此它不为空。Format()由于调用的特定实例,显式传入 null 并不能使其做到这一点。

于 2012-11-07T19:12:10.380 回答
6

如果您使用插值字符串($"",另一种格式化方式),则忽略 null 并跳过。所以

string nullString = null;
Console.WriteLine($"This is a '{nullString}' in a string");

将产生:“这是一个字符串中的''”。当然,您可以在 null 的情况下使用 null 合并运算符来生成所需的输出:

string nullString = null;
Console.WriteLine($"This is a '{nullString ?? "nothing"}' in a string");
于 2019-03-22T07:13:34.663 回答
2

第一个调用被解析为对 Format(object) 的调用,而第二个调用被解析为对 Format(object[]) 的调用。这些不同的重载以不同的方式处理空参数。

此处描述了重载解决方案。相关部分是对于 Format 的第二次调用,Format(params object[]) 的重载被扩展为 Format(object[]),它比 Format(object) 更受欢迎。文字 null 既是 object[] 又是 object,但 object[] 更具体,因此被选中。

于 2012-11-07T19:14:37.153 回答
-3

有以下两个区别:

  1. 这里,分配了 Null 值。

    Exception e = null;
    string msgOne = string.Format("An exception occurred: {0}", e);
    
  2. 这里,空值不能以字符串格式读取,这意味着类型转换错误。

    string msgTwo = string.Format("Another exception occurred: {0}", null);
    

我给你一个简单的例子:在这里,你不能将 NULL 值读取为字符串格式。

string str = null.toString();
于 2012-11-08T18:40:54.563 回答