我正在考虑替换代码如下:
foreach (var meshCut in meshCuts0)
{
ComputePolygons(meshCut, polygons);
}
foreach (var meshCut in meshCuts1)
{
ComputePolygons(meshCut, polygons);
}
Run Code Online (Sandbox Code Playgroud)
linq看起来像这样:
meshCuts0.Concat(meshCuts1).ForEach(m => ComputePolygons(m, polygons));
Run Code Online (Sandbox Code Playgroud)
我不知道linq是如何实现的,所以我不确定性能后果.我很感激一些帮助.
1)
Concat会创建一个列表副本,还是只是一个枚举器做这样的事情:
public static IEnumerable<T> Concat<T>(IEnumerable<T> a, IEnumerable<T> b)
{
foreach (var t in a)
{
yield return t;
}
foreach (var t in b)
{
yield return t;
}
}
Run Code Online (Sandbox Code Playgroud)
2)
这在Mono上是否会出现同样的行为?
3)
是否有任何参考解释如何实现linq api功能以提高性能?
谢谢!
编辑
好的,没有ForEach,所以我假设我也定义了这样的东西:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach(T item in source)
action(item);
}
Run Code Online (Sandbox Code Playgroud)
真正的问题是Concat是否会成为一个代价高昂的开销只是为了减少代码,感谢评论,我现在明白它不是.
编辑2
啊,Jon Skeet建议不要添加ForEach ......所以我不会!
http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx
Jon*_*eet 10
首先,如果你的代码只会工作还引入了ForEach可拓方法IEnumerable<T>.我建议你不要这样做 - 请参阅Eric Lippert的博客文章,原因我同意.
我建议你把它写成:
foreach (var meshCut in meshCuts0.Concat(meshCuts1))
{
ComputePolygons(meshCut, polygons);
}
Run Code Online (Sandbox Code Playgroud)
Concat执行得很好 - 它只是迭代第一个序列然后是第二个序列,随着时间的推移产生项目.它不会缓冲所有元素.对于你要添加的额外级别的间接性,会有非常轻微的性能损失,但这就是全部.
我期望单声道的行为以同样的方式- Concat是非常简单的.事实上,由于Mono是开源的,您可以自己检查.(它可能随着时间推移,当然......)
不久之前,我在博客上详细介绍了LINQ to Objects,从头开始重新实现了整个过程并记录了其性能的各个方面,包括哪些方面有改进的余地.有关详细信息,请参阅我的Edulinq博客系列.
这就是 linq concat 在底层的工作原理。
微软.net框架4.0:
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ConcatIterator<TSource>(first, second);
}
static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second) {
foreach (TSource element in first) yield return element;
foreach (TSource element in second) yield return element;
}
Run Code Online (Sandbox Code Playgroud)
单声道(来源:https://github.com/mono/mono/blob/master/mcs/class/System.Core/System.Linq/Enumerable.cs#L584)
public static IEnumerable<TSource> Concat<TSource> (this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
Check.FirstAndSecond (first, second);
return CreateConcatIterator (first, second);
}
static IEnumerable<TSource> CreateConcatIterator<TSource> (IEnumerable<TSource> first, IEnumerable<TSource> second)
{
foreach (TSource element in first)
yield return element;
foreach (TSource element in second)
yield return element;
}
Run Code Online (Sandbox Code Playgroud)
具体答复:
它不会创建任何副本,它只是枚举。
是的。
对于注重性能的人来说,源代码是最好的。
| 归档时间: |
|
| 查看次数: |
2599 次 |
| 最近记录: |