【发布时间】:2010-06-20 16:56:23
【问题描述】:
我想从 LINQ 查询中对每个对象调用 MyMethod,最好的方法是什么?
目前我正在使用:
.Select(x => { x.MyMethod (); return x; }).ToArray();
立即执行需要ToArray()。
有没有更简单的方法来写这个(没有foreach)
谢谢
【问题讨论】:
标签: linq
我想从 LINQ 查询中对每个对象调用 MyMethod,最好的方法是什么?
目前我正在使用:
.Select(x => { x.MyMethod (); return x; }).ToArray();
立即执行需要ToArray()。
有没有更简单的方法来写这个(没有foreach)
谢谢
【问题讨论】:
标签: linq
您可以指定自己的可重用扩展方法,在每个元素上运行 Action<>,然后 yield 返回它。
IEnumerable<T> Do(this IEnumerable<T> vals, Action<T> action) {
foreach(T elem in vals) {
action(elem);
yield return elem;
}
}
此类方法包含在Rx library 中,位于System.Interactive 命名空间下。
然后你可以简单地做
myCollection.Do(x => x.MyMethod()).ToArray();
【讨论】:
Rx 还包括Run 运算符,它与Do 类似,但也执行序列(无需将其存储在数组中的开销)。
xList 已经有了你需要的方法:.ForEach()。它对每个列表成员调用一个 Action。
List<x> fooList = ....Select(x => x).ToList();
fooList.ForEach(x => DoSomething(x));
【讨论】:
fooList.ForEach(DoSomething)
我创建了一个Apply 扩展方法:
public static IEnumerable<T> Apply<T>(this IEnumerable<T> source, Action<T> action)
{
foreach(var item in source)
{
action(item);
yield return item;
}
}
你可以按如下方式使用它:
var results = query.Apply(x => x.MyMethod()).ToArray();
其实这和List<T>.ForEach方法差不多,只是它返回源的项目,以便你可以继续对其应用序列操作符
【讨论】:
A for each 可能是最简单的方法,您可以编写一个扩展方法来执行 for each,但是 你真的不会有任何收获。
【讨论】:
在我看来,您不需要调用 .To___ 转换方法,因为您只期待副作用。 Reactive Extension 的 Do() 方法将是一个可行的选择。
通过使用 Do() 方法,您有两个优点(就我而言),
1) 延迟执行(您可以根据需要延迟立即执行)。
2) Do() 方法有不同的重载,让你对迭代有更多的控制。 例如:Do(onNext, OnError, OnCompleted) 重载
var deferQuery = query.Do(x => a.MyMethod(), ex => Console.WriteLine(ex.Message), () => Console.WriteLine("Completed"));
var immediateQuery = query.Do(x => a.MyMethod(), ex => Console.WriteLine(ex.Message), () => Console.WriteLine("Completed")).Run();
【讨论】: