如果我们想要一个IEnumerable<T>
表示两个IEnumerable<T>
的连接,我们可以使用LINQ Concat()
方法。
例如:
int[] a = new int[] { 1, 2, 3 };
int[] b = new int[] { 4, 5 };
foreach (int i in a.Concat(b))
{
Console.Write(i);
}
当然输出12345
。
我的问题是,为什么Concat()
没有重载,只是接受了一个T
类型的元素,使得:
int[] a = new int[] { 1, 2, 3 };
foreach (int i in a.Concat(4))
{
Console.Write(i);
}
将编译并生成输出:1234
?
在谷歌上搜索这个问题会产生一些SO问题,其中公认的答案表明,在寻求实现这一目标时,最好的方法是简单地执行a.Concat(new int[] {4})
。这很好(ish),但在我看来有点“不干净”,因为:
- 也许声明一个新的数组会对性能造成影响(尽管这可能几乎每次都可以忽略不计)
- 它看起来不像
a.Concat(4)
那样整洁、易读和自然
有人知道为什么这样的超载不存在吗?
另外,假设我的Google搜索没有让我失望--没有类似的LINQ扩展方法接受类型为T
的单个元素。
(我知道这是很容易滚动自己的扩展方法来产生这种效果-但这不只是使遗漏更奇怪?我怀疑会有一个原因,它的遗漏,但不能想象它可能是什么?)
更新:
承认这对夫妇的投票结束这作为意见为基础-我应该澄清,我不是在征求人们的意见,这是否将是一个很好的除了LINQ。
更多的我正在寻求理解为什么它不是LINQ的一部分的事实原因。
4条答案
按热度按时间mwyxok5s1#
在.NET Framework 4.7.1中,他们添加了
Prepend
和Append
方法,以将一个元素相应地添加到enumerable的开头和结尾。使用方法:
q9rjltbz2#
一个很好的理由是
IEnumerables
更像函数序列单子。但是由于LINQ直到.NET 3.0才出现,并且主要使用扩展方法实现,我可以想象他们省略了对
T
的单个元素的扩展方法。然而,它们确实包含了生成器函数,而不是扩展方法。具体如下:
您可以使用这些方法来代替自制扩展方法。您提到的两个用例可以解决为:
如果包含一个额外的重载作为语法糖,可能会更好。
没有明确的Unit函数是奇怪和有趣的
在Bart德斯梅特的博客文章MoreLINQ series中,使用
System.Linq.EnumerableEx
进行了说明,More LINQ with System.Interactive – Sequences under construction帖子专门处理了这个问题,使用以下适当命名的方法来构造单个元素IEnumerable
。这只不过是在 monad 上使用的返回函数(有时称为 unit)。
同样有趣的是Eric Lippert关于monads的博客系列,其中引用了part eight中的以下内容:
坦率地说,最后一个有点不可靠,我希望
Enumerable
上有一个静态方法专门用于生成一个单元素序列。此外,F#语言提供了
seq
类型:序列由
seq<'T>
类型表示,它是IEnumerable
的别名。因此,任何实现System.IEnumerable
的.NET Framework类型都可以用作序列。它提供了一个显式的unit函数
Seq.singleton
。结束
虽然这些都没有为我们提供“事实”来阐明这些序列结构在c#中没有显式存在的原因,但直到有设计决策过程知识的人分享这些信息,它确实突出了它值得了解更多。
y1aodyip3#
首先-你的谷歌搜索是罚款-没有这样的方法。我喜欢这个想法虽然。这是一个用例,如果你遇到,有它将是伟大的。
我怀疑它没有包含在API中是因为设计者没有看到对它的足够普遍的需求。
你说的对,创建一个只有一个元素的数组并不是那么直观。你可以通过下面的代码获得你想要的感觉和性能:
输出:
gijlo24d4#
哲学问题,我喜欢。
首先,您可以使用扩展方法轻松地创建该行为
我认为核心问题是IEnumerable是一个不可变的接口,它不应该被动态修改。
这可能(我使用could,因为我不在微软工作,所以我可能完全错了)是IEnumerable的modify部分不是很好开发的原因(这意味着你错过了一些方便的方法)。
如果必须修改该集合,请考虑使用List或其他接口。