使用Select(...)时运行select方法的次数。任何(...)?

时间:2015-01-19 02:10:48

标签: c# linq

首先,我有这个代码,如果满足条件,它将打破第二个循环。

例如,如果第一次满足条件,则不会枚举第二个循环的其他元素。

foreach (var evaluator in strategyEvaluators)
{
   foreach (var rule in concatedRules)
   {
        var isEntryRuleMet = evaluator.Evaluate(rule.Code);

        if (isEntryRuleMet)
        {
           matchedNames.Add(evaluator.Name);
           break;
        }
   }
}

但我也发现代码可以通过这种方式缩短:

foreach (var evaluator in strategyEvaluators)
{
   if (concatedRules.Select(rule=> evaluator.Evaluate(rule.Code)).Any(isEntryRuleMet => isEntryRuleMet))
   {
       matchedNames.Add(evaluator.Name);
   }
}

请注意,对于第二种方式,我不知道Select方法运行的次数。

Select返回true后Any是否停止了?或者它是否已完成运行,然后运行Any

3 个答案:

答案 0 :(得分:5)

  

在Any返回true后,Select是否正确停止?或者它是否已完成运行然后运行Any?

是的,确实如此。您可以这样认为:Select只要返回Any就会向false生成元素,一旦返回true,它就会停止。剩余的元素不会被生成。

这是一个简单的程序,它会使它恶化:

public static void Main()
{
    var query = Enumerable.Range(0,10).Select(x => GetNumber(x)).Any(x => x > 5);       
}


public static int GetNumber(int x)
{
    Console.WriteLine("GetNumber is called: {0}", x);
    return x;
}

// Output:

GetNumber is called: 0
GetNumber is called: 1
GetNumber is called: 2
GetNumber is called: 3
GetNumber is called: 4
GetNumber is called: 5
GetNumber is called: 6

答案 1 :(得分:2)

Select将在符合Any后停止运行。因此,只要Any返回true,它就会突破foreach循环并且不再实现集合。

您甚至可能希望将代码编写为

foreach (var evaluator in strategyEvaluators)
{
   if (concatedRules.Any(rule=>evaluator.Evaluate(rule.Code)))
   {
       matchedNames.Add(evaluator.Name);
   }
}

这样你甚至不必担心选择。

答案 2 :(得分:1)

第一个Any成功时,迭代停止。

您甚至可以通过以下方式缩小代码:

var matchedNames =
    strategyEvaluators
        .Where(evaluator =>
            concatedRules
                .Where(rule => evaluator.Evaluate(rule.Code))
                .Any())
        .Select(evaluator => evaluator.Name)
        .ToList();

如果已定义matchedNames,请尝试以下操作:

matchedNames
    .AddRange(
        strategyEvaluators
            .Where(evaluator =>
                concatedRules
                    .Where(rule => evaluator.Evaluate(rule.Code))
                    .Any())
            .Select(evaluator => evaluator.Name));