繁体   English   中英

为什么这三个LINQ代码产生不同(或错误)的结果?

[英]Why do these three pieces of LINQ code produce different (or erroneous) results?

以下是一些示例数据:

List<Book> books = new List<Book>()
{
    new Book(){Title = "artemis fowl: the time paradox", Pages = 380},
    new Book(){Title = "the lieutenant", Pages = 258},
    new Book(){Title = "the wheel of time", Pages = 1032},
    new Book(){Title = "ender's game", Pages = 404},
    new Book(){Title = "the sphere",  Pages = 657}
};  

背景:

以上使用Book类的简化版本。 当然,它包含许多领域。 我的最终目标是允许用户执行“高级”搜索,允许用户指定任何字段,并进一步允许用户使用布尔代数为特定字段指定关键字。

例如:在标题搜索文本框中:+(蛋糕|糕点)+〜恶魔

以上意思是:找到标题中有“蛋糕”或“糕点”字样的所有书籍,并且没有“恶魔”这个词。

问题:

宝贝步骤将导致最终的解决方案。 所以我最初有以下代码:

List<Func<Book, bool>> fs = new List<Func<Book, bool>>()
{
    b => b.Title.Contains("me"),
    b => b.Title.Contains("the")
};

var q2 = from b in books select b;
foreach (var f in fs)
    q2 = q2.Where(f);

foreach (Book b in q2)
{
    Console.WriteLine("Title:\t\t{0}\nPages:\t\t{1}\n",
                      b.Title, b.Pages);
}

上面的代码工作正常。 它会在标题中查找包含“和'我'的书籍。

阶段2

现在上面的过滤器类型为Func < Book ,bool>。 该类将是一个实体框架生成的类,我不想在我的UI层中使用,其中将输入搜索短语,并且将生成搜索过滤器以传递给BLL。

所以我有以下三次尝试:

var q = from b in books select b;

List<Func<string, bool>> filters  = new List<Func<string, bool>>()
{
    s => s.Contains("me"),
    s => s.Contains("the"),
};

//This works...
for (int i = 0; i != filters.Count; ++i)
{
    Func<string, bool> daF = filters[i];
    q = q.Where(b => (daF(b.Title)));
}     

            //This produces an exception...
            //Due to index in query?
//            for (int i = 0; i != filters.Count; ++i)
//            {
//                q = q.Where(b => ((filters[i])(b.Title)));
//            }

            //This runs but doesn't produce the proper output
//            foreach (Func<string, bool> filter in filters)
//              q = q.Where(b => filter(b.Title));

foreach (Book b in q)
{
    Console.WriteLine("Title:\t\t{0}\nPages:\t\t{1}\n",
                      b.Title, b.Pages);
}

第一个注释掉的部分触发索引器超出范围异常,表明i的值为2。

第二个评论出来的作品运行并产生输出,但它打印出5本书中的四本......除了标题为“恩德的游戏”的书外。 那是不对的...

所以,阅读我的帖子,我发现我无法记住解释每一个细节的坏习惯......

你去吧 请解释为什么不同的输出。 我想你可能暗示我目前的“解决方案”可能有所改进。

由于我们在这里使用LINQ to Objects,因此您应该能够使用All() 那你就不需要循环了。

var query = books.Where(book => filters.All(filter => filter(book.Title)));

这相当于:

var query = from book in books
            where filters.All(filter => filter(book.Title))
            select book;

至于为什么其他尝试不起作用,你正在关闭循环变量 通常,在循环中使用lambda函数时应该小心。 简单的解决方法是声明一个在lambdas中使用的单独变量。 请注意,您实际上是在第一个查询中间接执行此操作。 但是你根本不需要循环,应该使用上面的一个查询。

for (int i = 0; i != filters.Count; ++i)
{
    var index = i;
    q = q.Where(b => filters[index](b.Title));
}

foreach (Func<string, bool> f in filters)
{
    var filter = f;
    q = q.Where(b => filter(b.Title));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM