首先,我有这个代码,如果满足条件,它将打破第二个循环。
例如,如果第一次满足条件,则不会枚举第二个循环的其他元素。
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
?
答案 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));