如何在foreach中改进foreach

时间:2016-06-22 06:06:25

标签: c#

我在foreach循环中有一个foreach循环,如下所示:

// Item is an abstract class. Item1, Item2, etc. are his heirs.
List<Item> allItems = new List<Item> { new Item1(), new Item2(), new Item3(), new Item4() };
List<Type> affectedItems = new List<Type> { typeof(Item1), typeof(Item3) };

foreach(Item i in allItems)
    foreach(Type t in affectedItems)
        if(i.GetType().Equals(t))
        {
            // does something
        }

如何改进我的代码,以便内部循环不会浪费那么多时间检查列表中不存在的项目?

4 个答案:

答案 0 :(得分:5)

您使用的任何linq扩展方法(例如li.level1Where)都是一个额外的循环。

您需要最小化循环次数(尤其是嵌套循环次数),在您的情况下,最好的方法是使用快速查找数据结构:

Any

到目前为止,这是最快的方法,循环次数最少,并且需要 0.02毫秒,而其他方法需要 0.7

快速建议,无论何时进行循环处理,您希望优化查找要使用的数据结构,如List<Item> allItems = new List<Item>{ new Item1(), new Item2(), new Item3(), new Item4() }; HashSet<Type> affectedItems = new HashSet<Type>(){ typeof(Item1), typeof(Item3) }; foreach (Item i in allItems) { if (affectedItems.Contains(i.GetType())) { // Do Something } } HashSetDictionary,等。

答案 1 :(得分:2)

像这样编写单循环:

foreach (Item i in allItems.Where (item => affectedItems.
    Any (type => type.Equals (item.GetType ()))))

这将仅返回allItems中来自affectedItems的类型的项目。

与您的代码的唯一区别是Any将在找到第一个类型后停止搜索。这是唯一的改进。但您可以在break声明中添加if。那么这两个代码片段将是等效的。

答案 2 :(得分:1)

如果你有一个很大的类型列表,那么将列表更改为HashSet可能有助于提高性能,否则它没有太大的区别。

List<Item> allItems = new List<Item> { new Item1(), new Item2(), new Item3(), new Item4() };
HashSet<Type> affectedItems = new HashSet<Type> { typeof(Item1), typeof(Item3) };

var items = allItems.Where(item=> affectedItems.Contains(item.GetType())); 
foreach(var item in items)
{
        // does something
}

答案 3 :(得分:0)

这是最快的(我尝试你的代码,Linq有交叉和这个):

Array.ForEach(allItems.ToArray(), i => {
    var t = i.GetType();
    if (affectedItems.Contains(t)) {
        // Do Something
    }
});