谓词里面的谓词<>查询未命中?

时间:2017-07-06 06:16:27

标签: c# linq predicates

我需要为列表中的每个项目调用方法。所以,我使用Where<>查询如下,

List<string> list = new List<string>();
list.Add("Name1");
list.Add("Name2");
list.Add("Name3");

var name = list.Where(n =>
{
    return CheckName(n);
});

但在上述情况下,CheckName()未被击中。如果我使用FirstOrDefault<>,则会触发相同的方法。我不知道这是一个框架中断还是我走错了路。

作为附加信息,我使用的是.NET Framework 4.5。

有没有人遇到过这个错误?如果是这样,有没有解决方案来解决这个问题?

5 个答案:

答案 0 :(得分:3)

您错误地理解了Where条件的结果。由于linq被执行了,它只会在实现时进入where条件(通过ToList / FirstOrDefault / Sum等等。

Where实际上从未在您当前的代码中实现(它与您使用FirstOrDefault时所经历的那样),因此它永远不会进入CheckName方法。然后,由于Where永远不会返回null,但“最坏情况”将是一个空集合,而不是null,结果为true

如果您进行调试,则会在此结尾处看到name等于true。要“克服”这取决于你想要的输出:

  1. 如果您想知道您是否有任何与谓词匹配的项目:

    var result = list.Any(CheckName);
    
  2. 如果要检索与谓词匹配的内容:

    var result = list.Where(CheckName);
    

    如果以后要查询并检查results是否包含任何内容,请执行以下操作:

    if(result.Any()) { /* ... */ }
    

    如果您只想要结果(从而实现查询):

    list.Where(CheckName).ToList();
    
  3. 在这里阅读更多关于linq被执行的信息:

    正如旁注,了解如何更改当前代码:

    var name = list.Where(n =>
    {
        return CheckName(n);
    })
    

    要:

    var name = list.Where(n => CheckName(n));
    

    最终:

    var name = list.Where(CheckName);
    

答案 1 :(得分:2)

LINQ有延迟执行主体,这意味着除非您访问$(function() { $('a.page-scroll').bind('click', function(event) { $("html, body").animate({ scrollTop: 0 }, 1500); event.preventDefault(); }); }); 变量,否则不会执行查询。如果你想立即执行它,(仅举例)最后添加name,这正是.ToList()所做的。它立即执行而不是延迟执行。

FirstOrDefault

同样var name = list.Where(n => { return CheckName(n); }).ToList() != null; 条件结果永远不会是where。即使null中的list中没有任何对象满足CheckName中的条件,where也会返回空集合。

答案 2 :(得分:1)

由于Linq的延迟执行,未执行CheckName()方法。在您实际访问之前,不会执行实际的语句。因此,在您的情况下,对于CheckName(),您应该执行以下操作:

var name = list.Where(n =>
{
    return CheckName(n);
}).ToList();

答案 3 :(得分:0)

如果你需要为列表中的每个项目调用一个方法,那么你应该使用一个简单的for循环:

foreach var name in list
  CheckName(name);

仅仅因为LINQ可用,并不意味着它应该在有集合的任何地方使用。编写有意义且自我评论的代码非常重要,并且在此处使用它同时在您的逻辑中引入了一个缺陷,使您的代码更难以阅读,理解和维护。它是用于所述目的的错误工具

毫无疑问,您有其他要求未在此处说明,例如&#34;我想检查列表中的每个名称,并确保没有任何名称为空&#34;。您可以并且可能应该使用linq,但它看起来更像

bool allNamesOK = list.All(n => n != null);

此代码紧凑且读取良好;我们可以清楚地看到意图(虽然我不打电话给列表&#34;列表&#34; - &#34;名字&#34;会更好)

答案 4 :(得分:0)

当您查看Where - 方法source代码时,您可以轻松了解原因:

    internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) {
        foreach (T t in enumerable) {
            if (where(t)) {
                yield return t;
            }
        }
    }

只有在实际访问返回的IEnumerable<T>后,yield才会导致执行。这就是所谓的延迟执行。