String.format如何处理null值



在下面的以下代码中,为什么两个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);
}

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

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

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

在第二个示例中,通过提供null,您很可能会击中String.Format(string,params object[]),根据文档,它会在以下内容时提出ArgumentNullException

格式或args为null。

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

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

为什么击中params object[]超载?可能是因为null不是对象,而params的工作方式是,您可以将每个值作为call 中的新对象传递给每个值值。也就是说,以下是相同的:

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

在您的第一个示例中,您正在击中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()的特定实例。

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

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

将产生:"这是字符串中的''。当然,如果无效,您可以使用零合并操作员产生所需的输出:

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

第一个呼叫被解析为呼叫格式(对象),而第二个呼叫被解析为呼叫的格式(object [])。这些不同的过载以不同的方式处理零参数。

重载分辨率在此处描述。相关的部分是,对于第二个呼叫格式,格式(params object [])的过载被扩展到格式(object []),该格式比格式(object)优先。字面的null既是对象[],又是对象,但是对象[]更具体,因此被选择。

有两个区别:

  1. 在这里,分配了空值。

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

最新更新