我想在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;
        }
    }
}