使用 where/lambda 和 for each 之间的区别

Difference between using where/lambda and for each

我是 C# 的新手,在字典上发现了这个函数。

 _objDictionary.Keys.Where(a => (a is fooObject)).ToList().ForEach(a => ((fooObject)a).LaunchMissles());

我的理解是,这实质上是将每个作为 fooObject 的键放入一个列表中,然后执行每个键的 LaunchMissles 函数。这与像这样使用 for each 循环有何不同?

foreach(var entry in _objDictionary.Keys)
{
    if (entry is fooObject)
    {
        entry.LaunchMissles();
    }
}

编辑:响亮的意见似乎是没有功能差异。

这是滥用 LINQ 的一个很好的例子 - 声明并没有以任何其他方式变得更具可读性或更好,但有些人只是喜欢将 LINQ 无处不在。尽管在这种情况下,您可以通过以下方式从两全其美:

foreach(var entry in _objDictionary.Keys.OfType<FooObject>())
{
    entry.LaunchMissles();    
}

请注意,在您的 foreach 示例中,您缺少对 FooObject 的转换以调用 LaunchMissles.

总的来说,Linq 不是 Voodomagic,它在幕后做的事情与您不使用它时需要编写的内容相同。 Linq 只是让事情更容易编写,但它不会在性能方面击败常规代码(如果它真的等效)

在你的情况下,你的 "oldschool" 方法非常好,在我看来是有利的

foreach(var entry in _objDictionary.Keys)
{
    fooObject foo = entry as fooObject;
    if (foo != null)
    {
        foo .LaunchMissles();
    }
}

关于 Linq 方法:

将序列具体化为列表只是为了在其上调用一个方法,这与上面的代码相同,只是在浪费资源并降低其可读性。

在您的示例中,它不会产生差异,但如果源不是 Collection(如 Dictionary.Keys 是)而是真正以惰性方式工作的 IEnumerable,那么就会产生巨大的影响。

惰性求值旨在在需要时产生项目,在其间调用 ToList 将首先收集所有项目,然后再实际执行 ForEach。 虽然普通的 foreach 方法会获取一个项目,然后处理它,然后获取下一个,依此类推。

如果你真的想使用 "Linq-Foreach" 而不是使用列表实现,而是使用你自己的扩展方法(就像你的问题下面的评论中提到的那样)

public static class EnumerableExtensionMethods
{ 
    public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action)
    {
        foreach(T item in sequence) 
            action(item);
    }
}

那么最好还是使用常规的 foreach 滚动,除非您将 foreach 主体放入不同的方法中

sequence.ForEach(_methodThatDoesThejob);

这是唯一的"for me acceptable"使用方法。