在下面的代码中,为什么两个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
:
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();
在你的第一个例子中,你正在击中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并不会使它成功。
第一个调用被解析为对Format(对象)的调用,而第二个调用被解析为对Format(object [])的调用。这些不同的重载以不同方式处理空参数。
here描述了过载分辨率。相关部分是对于第二次调用Format,Format(params object [])的重载被扩展为Format(object []),它优先于Format(object)。文字null既是对象[]又是对象,但是对象[]更具体,因此选择它。
如果您使用插值字符串($“”,另一种格式化方式),则忽略空值,跳过该值。所以
string nullString = null;
Console.WriteLine($"This is a '{nullString}' in a string");
将产生:“这是一个字符串中的''。当然,如果为null,您可以使用null coalescing运算符来生成所需的输出:
string nullString = null;
Console.WriteLine($"This is a '{nullString ?? "nothing"}' in a string");
以下是两个不同之处:
Exception e = null;
string msgOne = string.Format("An exception occurred: {0}", e);
string msgTwo = string.Format("Another exception occurred: {0}", null);
我举一个简单的例子:在这里,你不能将NULL值作为字符串格式读取。
string str = null.toString();