使用 Select(...).Any(...) 时 select 的方法是 运行 多少次?
How many times select's method is run when using Select(...).Any(...)?
首先,我有这段代码,如果满足条件,它会中断第二个循环。
所以比如第一次满足条件,就不会枚举第二个循环的其他元素
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
是在 Any
returns 之后立即停止吗?还是说完了运行ning然后Any
就是运行?
Is Select stopped right after Any returns true? Or is it finished running and then Any is run?
是的,是的。你可以这样想:Select
产生元素到 Any
只要它 returns false
,一旦它 returns true
,它stops.Remaining 个元素未生成。
这是一个演示它的简单程序:
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
Select
满足Any
后会停止运行。因此,一旦 Any returns 为真,它就会跳出 foreach 循环,不再具体化集合。
您甚至可能希望将代码编写为
foreach (var evaluator in strategyEvaluators)
{
if (concatedRules.Any(rule=>evaluator.Evaluate(rule.Code)))
{
matchedNames.Add(evaluator.Name);
}
}
这样你根本不用担心 select。
当第一个 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));
首先,我有这段代码,如果满足条件,它会中断第二个循环。
所以比如第一次满足条件,就不会枚举第二个循环的其他元素
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
是在 Any
returns 之后立即停止吗?还是说完了运行ning然后Any
就是运行?
Is Select stopped right after Any returns true? Or is it finished running and then Any is run?
是的,是的。你可以这样想:Select
产生元素到 Any
只要它 returns false
,一旦它 returns true
,它stops.Remaining 个元素未生成。
这是一个演示它的简单程序:
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
Select
满足Any
后会停止运行。因此,一旦 Any returns 为真,它就会跳出 foreach 循环,不再具体化集合。
您甚至可能希望将代码编写为
foreach (var evaluator in strategyEvaluators)
{
if (concatedRules.Any(rule=>evaluator.Evaluate(rule.Code)))
{
matchedNames.Add(evaluator.Name);
}
}
这样你根本不用担心 select。
当第一个 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));