string.Format 如何处理空值?

Posted

技术标签:

【中文标题】string.Format 如何处理空值?【英文标题】:How does string.Format handle null values? 【发布时间】:2012-11-07 19:04:09 【问题描述】:

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

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

【问题讨论】:

您可能在第二个示例中遇到了params override,String.Format 测试了数组在继续迭代集合和插入值之前是否已填充。 @BradChristie 你应该把它写成答案。 【参考方案1】:

我在这里猜测,但它看起来是你打哪个重载呼叫的区别; 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 的工作方式是您可以在调用中将either 每个值作为新对象传递值的数组。也就是说,下面是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();

【讨论】:

另外:试试string.Format("Occurred: 0", (object[])null)string.Format("Occurred: 0", (object)null) 之间的区别。还有一种可能性:string.Format("Occurred: 0", new[] (object)null, )。我猜,问题只发生在第一种情况下。【参考方案2】:

在您的第一个示例中,您点击了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 并不会让它这样做。

【讨论】:

【参考方案3】:

如果您使用插值字符串($"",另一种格式化方式),则 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】:

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

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

【讨论】:

【参考方案5】:

有以下两个区别:

    在这里,分配了 Null 值。

    Exception e = null;
    string msgOne = string.Format("An exception occurred: 0", e);
    

    这里,Null 值不能以字符串格式读取,这意味着类型转换错误。

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

我给你一个简单的例子: 此处,您无法将 NULL 值读取为字符串格式。

string str = null.toString();

【讨论】:

以上是关于string.Format 如何处理空值?的主要内容,如果未能解决你的问题,请参考以下文章

从 Spark 写入镶木地板时如何处理空值

使用 protobuf-net 序列化数组时如何处理空值?

@Tableau 设计技巧 10:Tableau中如何处理空值

如何处理空的 JSON 对象?

RestKit:如何处理空的 response.body?

python中的all()如何处理空列表