我想在LINQ中执行以下等效操作,但我无法确定如何执行:
IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());
真正的语法是什么?
我想在LINQ中执行以下等效操作,但我无法确定如何执行:
IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());
真正的语法是什么?
当前回答
让你的副作用远离我的IEnumerable
我想在LINQ中执行以下等效操作,但我无法确定如何执行:
正如其他人在国内外指出的,LINQ和IEnumerable方法预计不会产生副作用。
你真的想对IEnumerable中的每个项目“做点什么”吗?那么foreach是最好的选择。当这里出现副作用时,人们并不感到惊讶。
foreach (var i in items) i.DoStuff();
我打赌你不想有副作用
然而,根据我的经验,通常不需要副作用。通常情况下,有一个简单的LINQ查询等待被发现,并伴随着Jon Skeet、Eric Lippert或Marc Gravell的StackOverflow.com回答,解释如何做您想要的事情!
一些示例
如果您实际上只是在聚合(累积)一些值,那么应该考虑聚合扩展方法。
items.Aggregate(initial, (acc, x) => ComputeAccumulatedValue(acc, x));
也许您想从现有值创建一个新的IEnumerable。
items.Select(x => Transform(x));
或者你想创建一个查找表:
items.ToLookup(x, x => GetTheKey(x))
可能性的列表(双关语并非完全有意)还在继续。
其他回答
在Jon Skeet的启发下,我扩展了他的解决方案:
扩展方法:
public static void Execute<TSource, TKey>(this IEnumerable<TSource> source, Action<TKey> applyBehavior, Func<TSource, TKey> keySelector)
{
foreach (var item in source)
{
var target = keySelector(item);
applyBehavior(target);
}
}
客户:
var jobs = new List<Job>()
{
new Job { Id = "XAML Developer" },
new Job { Id = "Assassin" },
new Job { Id = "Narco Trafficker" }
};
jobs.Execute(ApplyFilter, j => j.Id);
...
public void ApplyFilter(string filterId)
{
Debug.WriteLine(filterId);
}
根据PLINQ(从.Net 4.0开始提供),您可以执行
IEnumerable<T>.AsParallel().ForAll()
在IEnumerable上执行并行foreach循环。
又一个ForEach示例
public static IList<AddressEntry> MapToDomain(IList<AddressModel> addresses)
{
var workingAddresses = new List<AddressEntry>();
addresses.Select(a => a).ToList().ForEach(a => workingAddresses.Add(AddressModelMapper.MapToDomain(a)));
return workingAddresses;
}
这种“功能方法”抽象泄露了大量时间。在语言层面上没有任何东西可以防止副作用。只要你能让它为容器中的每个元素调用lambda/委托,你就会得到“ForEach”行为。
例如,这里有一种将srcDictionary合并到destDictionary的方法(如果键已经存在-重写)
这是一个黑客,不应该在任何生产代码中使用。
var b = srcDictionary.Select(
x=>
{
destDictionary[x.Key] = x.Value;
return true;
}
).Count();
如果您想充当枚举滚动,则应生成每个项。
public static class EnumerableExtensions
{
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (var item in enumeration)
{
action(item);
yield return item;
}
}
}