gpt4 book ai didi

c# - 我在这个谓词链中缺少什么?

转载 作者:可可西里 更新时间:2023-11-01 09:05:53 25 4
gpt4 key购买 nike

注意:就在发布这个问题之前,我突然想到有一种更好的方法来完成我想要完成的事情(我觉得这很愚蠢):

IEnumerable<string> checkedItems = ProductTypesList.CheckedItems.Cast<string>();
filter = p => checkedItems.Contains(p.ProductType);

好吧,是的,我已经意识到了这一点。但是,无论如何我都会发布这个问题,因为我仍然不太明白为什么我(愚蠢地)尝试做的事情没有奏效。


我认为这会非常容易。原来这让我很头疼。

基本思路:在CheckedListBox中显示所有ProductType属性值被选中的项目。

实现:

private Func<Product, bool> GetProductTypeFilter() {
// if nothing is checked, display nothing
Func<Product, bool> filter = p => false;

foreach (string pt in ProductTypesList.CheckedItems.Cast<string>()) {
Func<Product, bool> prevFilter = filter;
filter = p => (prevFilter(p) || p.ProductType == pt);
}

return filter;
}

但是,假设项目“Equity”和“ETF”都在 ProductTypesList(CheckedListBox)中选中。那么由于某种原因,下面的代码只返回“ETF”类型的产品:

var filter = GetProductTypeFilter();
IEnumerable<Product> filteredProducts = allProducts.Where(filter);

我猜这可能与一些自引用困惑有关,其中 filter 本质上被设置为 本身。我认为也许使用 ...

filter = new Func<Product, bool>(p => (prevFilter(p) || p.ProductType == pt));

...可以解决问题,但没有这样的运气。任何人都可以看到我在这里缺少什么吗?

最佳答案

我相信您这里有一个修改后的闭包问题。 pt 参数绑定(bind)到 lambda 表达式中,但随着循环的进行而改变。重要的是要意识到在 lambda 中引用变量时捕获的是变量,而不是变量的值

在循环中,这有一个非常重要的分支——因为循环变量正在改变,而不是被重新定义。通过在循环内创建一个变量,您将为每次迭代创建一个新变量 - 然后允许 lambda 独立捕获每个变量。

期望的实现是:

foreach (string pt in ProductTypesList.CheckedItems.Cast<string>()) {
string ptCheck = pt;
Func<Product, bool> prevFilter = filter;
filter = p => (prevFilter(p) || p.ProductType == ptCheck);
}

Eric Lippert 曾写过关于这种特定情况的文章:

此外,请参阅问题 Access to Modified Closure (2) 以了解闭包变量会发生什么情况。 The Old New Thing 博客上还有一系列文章对此有一个有趣的观点:

关于c# - 我在这个谓词链中缺少什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2389581/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com