Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 选择';使用Select(…)时会运行s方法。是否有(…)?_C#_Linq - Fatal编程技术网

C# 选择';使用Select(…)时会运行s方法。是否有(…)?

C# 选择';使用Select(…)时会运行s方法。是否有(…)?,c#,linq,C#,Linq,首先,我有这个代码,如果条件满足,它将中断第二个循环 例如,如果第一次满足条件,则第二个循环的其他元素将不会被枚举 foreach (var evaluator in strategyEvaluators) { foreach (var rule in concatedRules) { var isEntryRuleMet = evaluator.Evaluate(rule.Code); if (isEntryRuleMet) {

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

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

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
方法将运行多少次

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

Select是否在返回true后立即停止?或者它运行完毕,然后运行任何一个

是的。您可以这样想:
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

Select
将在满足
Any
后停止运行。因此,一旦返回true,它就会跳出foreach循环,不再具体化集合

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

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

这样,您甚至不必担心选择问题。

当第一次
任何
成功时,迭代就会停止

您甚至可以通过以下操作使代码更小:

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));

是的,这被称为“惰性评估”,并且LINQtoObjects扩展方法尽可能努力使用惰性评估。一些没有(因为它们不能)的是
ToList
ToArray
、和
OrderBy
.concatedRules.Where(rule=>evaluator.Evaluate(rule.code))。当我这样做时,Any()会更准确:concatedRules.Where(rule=>evaluator.Evaluate(rule.code)).Any(),而不是提示我这样做:concatedRules.Any()(rule=>strategyAlert.Evaluate(rule.Code))谢谢,这是正确的链接: