有没有更好的方法来编写LINQ函数?

问题描述 投票:1回答:2

所以,我是LINQ的新手,并试图弄清楚如何过滤项目。那是我的任务

public async Task<PagedList<Item>> GetItems (ItemParams itemParams) {
    var items = _context.Items.AsQueryable ();
    if (itemParams.CategoryId > 0) {
        var category = GetCategory (itemParams.CategoryId);

        items = items.Where (i => FilterItems (i, category.Result));

    }
    return await PagedList<Item>.CreatAsync (items, itemParams.PageNumber, itemParams.PageSize);
}

以及决定返回哪些项目的函数

static bool FilterItems (Item item, Category category) {

    if (item.CategoryId == category.Id) {
        return true;
    }
    if (category.Children.Count > 0) {
        foreach (Category cat in category.Children) {
          return  FilterItems (item, cat);
        }
    }
    return false;
}

获取类别功能

    public async Task<Category> GetCategory (int? id) {
        if (id == null) {
            return null;
        }
        var categories = _context.Categories.Include (x => x.Children).AsEnumerable ().Where (c => c.Id == id);
        categories = Traverse (categories);
        var category = await Task.FromResult (categories.First (c => c.Id == id));
        return category;
    }
c# linq asp.net-core-2.1
2个回答
1
投票

您的过滤器将无法按预期工作,因为foreach在第一个循环返回。 FilterItems这个名字也不直观。

static bool ContainsItem(Category category, Item item)
{
    return
        category.Id == item.CategoryId ||
        category.Children.Any(c => ContainsItem(c, item);
}

由于C#执行|| Operator的短路评估,如果第一项匹配,则不会评估第二项。请注意,这不是一个肮脏的技巧,但它是C#规范的一部分。


1
投票

从代码中看,如果item在当前类别或任何子类别中,FilterItems()似乎返回true?

如果是这种情况,我认为您当前的代码存在问题:对FilterItems()的递归调用会立即返回第一个子类别的结果而不检查其他子类别

这是修改后的代码:

public static bool InCategoryOrSubCategory(Item item, Category category)
{
    return item.CategoryId == category.Id ||
        category.Children.Any(subCategory => InCategoryOrSubCategory(item, subCategory));
}

我将名称更改为InCategoryOrSubCategory以使其更清晰

这是一个curried版本,使Where调用稍微更好(但方法本身有点更神秘):

public static Func<Item, bool> InCategoryOrSubCategory(Category category) 
{
    return item => 
        item.CategoryId == category.Id || 
        category.Children.Any(subCategory => InCategoryOrSubCategory(subCategory)(item));
}

用法:

items.Where(InCategoryOrSubCategory(category))
© www.soinside.com 2019 - 2024. All rights reserved.