string.Format如何处理空值?

时间:2012-11-07 19:04:09

标签: c# .net string.format

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

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

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

5 个答案:

答案 0 :(得分:47)

我在这里猜测,但它看起来是你正在击中的超负荷电话的区别。 String.Format有多个重载,只是你要点击的。

在第一个例子中,你可以点击String.Format(string,object)

在提供null的第二个示例中,您最有可能点击String.Format(string,params object[]),根据文档,如果出现以下情况,则会ArgumentNullException

  

format或args为null。

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

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

为什么它会超过params object[]重载?可能是因为null不是对象,params的工作方式是你可以将 每个值作为调用传递一个值数组。也就是说,以下是one in the same

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

答案 1 :(得分:11)

在您的第一个示例中,您正在点击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");
    }
...
}

...呃,这是你的问题,就在那里!第一次调用是将它包装在一个新数组中,所以它不是null。由于Format()的特定实例正在调用,因此明确地传入null并不会使它成功。

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

如果您使用插值字符串($“”,这是另一种格式),则将忽略null并跳过该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");

答案 4 :(得分:-3)

以下是两个不同之处:

  1. 此处,分配了空值。

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

    string msgTwo = string.Format("Another exception occurred: {0}", null);
    
  3. 我举一个简单的例子: 在这里,您不能将NULL值作为字符串格式读取。

    string str = null.toString();