字符串拼接的行为表现

6

我正在使用 string.Join() 来使用分隔符连接值 - 这是我使用 User 类的简化示例:

public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

这是我的结果:
User uItem = new User() { Age = 10, Name = null };

string item1 = string.Join(";", string.Empty, 1); // returns ";1"  
string item2 = string.Join(";", null, 1); // returns ""        
string item3 = string.Join(";", uItem.Name, uItem.Age, 1); // returns ""
string item4 = string.Join(";", 1, null); //returns "1;"
string item5 = string.Join(";", null, uItem.Age, 1); // throws null exception

起初我很惊讶 item2 的行为与 item1 不同,它返回了一个 "" 而不是 ";1"

是否有一条规则,类似于 null 是允许的,但不允许在第一个项目中使用?

我的问题:为什么item3返回"",而item5会抛出异常?输入值相等。

2个回答

13

因为你在调用不同的重载函数:

string item5 = string.Join(";", null, uItem.Age, 1); // throws null exception

将要调用

public static string Join(string separator, string[] value, int startIndex, int count);

尝试在Visual Studio中执行"转到定义"命令,然后查看(相关内容)。所以你正在将null作为string[] value传递。

关于此:

string item2 = string.Join(";", null, 1); // returns ""

String.Join Method (String, Object[])页面中有一条备注:

如果values的第一个元素为null,则Join(String, Object[])方法不会连接values中的元素,而是返回String.Empty。 可以使用多种解决此问题的方法。 最简单的方法是将数组的第一个元素赋值为String.Empty,如下例所示

我认为这个(对第一个元素的特殊处理)相当愚蠢(即使String.Concat Method (Object[])也没有它)。

请注意,另一个重载String.Join<T> Method (String, IEnumerable<T>)没有这种特殊处理:

string item2bis = string.Join(";", (IEnumerable<object>)new object[] { null, 1 }); // returns ";1"

如果有人对此感兴趣,那并不是因为什么随机的原因... 在 Microsoft 的 String.Join 实现中有明确的 C# 代码:

if (values.Length == 0 || values[0] == null)
    return String.Empty;

@fubo:因为他传递了 ";", uItem.Name, uItem.Age, 1。第一个参数是分隔符,第二个参数是空的 string[],第三个是起始索引,最后一个是计数。如果他再添加另一个参数,就会采用 params object[] 重载。 - Tim Schmelter
1
@fubo string.Join(";", null, uItem.Age, 1);; ";" 是 stringnullstring[]uItem.Ageint1int - xanatos
1
很好的回答xanatos,也是这个“设计缺陷”的一个很好的演示。 - Patrick Hofman

7
根据文档(我加粗的部分),如果separator为空或者values的任何元素不是第一个元素且为空,则使用空字符串(String.Empty)。因此,对null的不同处理是有设计意图的。另外,正如xanatos所指出的那样,如果使用另一种重载方式,会导致异常,因为如果value为null,它将抛出参数异常(ArgumentNullException)。

2
没有解释异常,这是其中一个应该可以接受两个答案的问题。 - Tim Schmelter
1
这并没有解释为什么 item5 会抛出异常。它只是说空字符串将被用来代替 null - Yuval Itzchakov
@TimSchmelter 现在应该已经修复了。 - Patrick Hofman
谢谢您的回复,如果可以的话,我会接受两个答案。 - fubo
没问题。不用谢 @fubo Xanatos 做得很好。 - Patrick Hofman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接