字符串是什么原因。Join 需要采用数组而不是 IEnumerable?

What is the reason string.Join needs to take an array instead of an IEnumerable?

提问人:sbi 提问时间:10/19/2010 更新时间:10/19/2010 访问量:547

问:

正如标题所说:为什么需要采用数组而不是 IEnumerable?这一直让我很烦恼,因为我必须添加一个.ToArray(),当我需要从 LINQ 表达式的结果创建联接字符串时。string.Join

我的经验告诉我,我在这里遗漏了一些明显的东西。

c#

评论

2赞 Anthony Pegram 10/19/2010
你会很高兴地知道它在 .NET 4 中接受IEnumerable<T>
0赞 asawyer 10/19/2010
我的猜测是它是在 IEnumerable 存在之前添加的。
0赞 GôTô 10/19/2010
字符串。Join 早在 Linq 之前就已经存在了。它如何困扰你?只需多写几个字符即可。

答:

3赞 Jon Skeet 10/19/2010 #1

它不再了。.NET 4 添加了一些重载,使其更易于使用。特别是,您不仅不需要传入数组 - 它也不需要是字符串序列。String.Join(String, IEnumerable<T>) 将调用序列中的每个项。ToString

当然,如果不使用 .NET 4,但要执行大量字符串联接操作,则始终可以编写自己的方法。

评论

0赞 sbi 10/19/2010
你是在告诉我 .NET < 4 没有理由这样做吗?
0赞 Jon Skeet 10/19/2010
@sbi:是的。这只是 MS 可能没有意识到对开发人员同样有用的东西。据我所知,它不需要 .NET 4 的任何新功能。
0赞 sbi 10/22/2010
在这里,我期待一个冗长而有教育意义的处理,说明为什么它必须是一个阵列......
8赞 LukeH 10/19/2010 #2

在 .NET 4 中引入了采用 IEnumerable<T> 参数的 Join 重载 - 如果您不使用 .NET 4,那么恐怕您只能传递数组或编写自己的实现。

我猜原因很简单,在第一次设计框架时,它被认为不够重要。 随着 LINQ 的引入,变得更加突出。IEnumerable<T>

(当然,在设计 .NET 时,它没有泛型类型,但如果他们认为值得的话,他们没有理由不能使用普通的非泛型类型来做到这一点。IEnumerable

如果你觉得需要它并且无法升级到 .NET 4,则没有理由不能推出自己的版本。JoinIEnumerable<T>

评论

0赞 Esko 10/19/2010
...除非有人将数组写入 IEnumerable<T>,否则我假设?无论如何,这就是我们 Java 人习惯做的事情。
9赞 jason 10/19/2010 #3

升级到 .NET 4.0 并使用接受 .否则,请接受这是一个长期悬而未决的问题,直到 .NET 4.0 才得到解决。您也可以通过创建自己的扩展方法来解决问题!IEnumerable<string>

public static class StringEnumerableExtensions {
    public static string Join(this IEnumerable<string> strings, string separator) {
        return String.Join(separator, strings.ToArray());
    }
}

用法:

IEnumerable<string> strings;
Console.WriteLine(strings.Join(", "));

评论

0赞 sbi 10/19/2010
Jason,非常感谢,编程变得如此快乐!:)
0赞 sbi 10/22/2010
顺便说一句,我实际上在上面写了一个。我深深地爱上了我,我经历了 100kLoC 并适应了 .Join<T>(this IEnumerable<T> strings, string separator)string.Join()
0赞 supercat 10/19/2010 #4

我猜 String.Join 需要能够遍历数组两次(一次用于测量长度,一次用于复制)。某些实现 iEnumerable 的类可以通过执行一次传递来计算长度,在枚举器上调用 Reset,并使用第二次传递来复制数据,从而成功联接到字符串数组中,但由于 iEnumerable 既不支持 Capabilities 属性,也不支持 iMultiPassEnumerable 等一系列派生类,因此 String.Join 可以安全地接受 iEnumerable 的唯一方法是 (1) 枚举到某种类型的列表并运行联接在此基础上,(2)猜测目标字符串大小,并根据需要重新分配,或(3)组合方法,将短字符串分组为最多8K的簇,然后将所有簇组合成最终结果(这将是预连接的簇和来自原始数组的长字符串的混合)。

虽然我当然承认 String.Join 包含将 iEnumerable 转换为 List 的开销会很方便,但我不认为它会提供比手动执行此类转换更高的效率(与 String.Join 的数组版本不同,后者比手动单独连接字符串更有效)。