LINQ难度大

时间:2010-12-02 18:11:48

标签: c# linq

我在使用IEnumerable和LINQ时遇到了困难。也许我完全不了解它。

我有假文件的数据源(“PlumFile”)和一些过滤器。每个过滤器都有一个Fits(PlumFile),用于确定参数是否适合该过滤器。每个过滤器还有一个枚举,表明它是“和”,“或”,还是“不是”。

以下是我尝试将所有这些过滤器组合到查询中的方法:

    public ObservableCollection<PlumFile> FoundFiles
    {
        get
        {
            ObservableCollection<PlumFile> searchResults = new ObservableCollection<PlumFile>();

            // get the data source
            IEnumerable<PlumFile> query = PlumData.GetFiles();

            foreach (FilterConstraint filter in filters)
            {
                // debugging
                IList<PlumFile> oldQuery = query.ToList();

                switch (filter.QueryCombiningRule)
                {
                    case FilterConstraint.QueryRule.And:
                        query = query.Where(file => filter.Fits(file));
                        break;
                    case FilterConstraint.QueryRule.Or:
                        query = query.Concat(PlumData.GetFiles().Where(file => filter.Fits(file)));
                        break;

                    // is this really how I want to do 'not'?
                    case FilterConstraint.QueryRule.Not:
                        query = query.Where(file => !filter.Fits(file));
                        break;
                }

                // debugging
                IList<PlumFile> currQuery = query.ToList();

            }

            query = query.Distinct();

            foreach (PlumFile file in query)
            {
                searchResults.Add(file);
            }

            return searchResults;
        }
    }

我不确定我做错了什么。对于某些查询,它工作正常。对于其他人,它失败了。

如果我有一个“和”过滤器,它可以正常工作。然后我添加一个“不”过滤器,不应该过滤掉已经选择的任何东西,但一切都被删除了。这是为什么?

(我正在为Silverlight 4应用程序执行此操作,但我认为这不重要。)

更新: 过滤器约束的一个示例:

public class NameFilterConstraint : FilterConstraint
{
    public string Name { get; set; }

    public override bool Fits(PlumFile plumFile)
    {
        return plumFile.Name.Contains(Name);
    }

    public override string Description
    {
        get
        {
            return ToString();
        }
    }

    public override string ToString()
    {
        return String.Format("Name contains '{0}'", Name);
    }
}

更新2 :这是一个非LINQ版本,没有我之前提到的错误:

public ObservableCollection<PlumFile> FoundFiles
        {
            get
            {
                ObservableCollection<PlumFile> searchResults = new ObservableCollection<PlumFile>(PlumData.GetFiles().ToList());

                foreach (FilterConstraint filter in filters)
                {
                    switch (filter.QueryCombiningRule)
                    {
                        case FilterConstraint.QueryRule.And:
                            foreach (PlumFile file in searchResults.ToList())
                            {
                                if (! filter.Fits(file))
                                {
                                    searchResults.Remove(file);
                                }
                            }
                            break;

                        case FilterConstraint.QueryRule.Or:
                            foreach (PlumFile file in PlumData.GetFiles())
                            {
                                if (filter.Fits(file))
                                {
                                    searchResults.Add(file);
                                }
                            }
                            break;

                        case FilterConstraint.QueryRule.Not:
                            foreach (PlumFile file in searchResults.ToList())
                            {
                                if (filter.Fits(file))
                                {
                                    searchResults.Remove(file);
                                }
                            }
                            break;
                    }
                }

                return new ObservableCollection<PlumFile>(searchResults.Distinct());
            }
        }

所以,我想我的问题已经解决了,尽管我仍然对LINQ的错误感到好奇。也许我的意图(在上一个例子中明确说明)没有正确地翻译成LINQ?

2 个答案:

答案 0 :(得分:2)

这里只是一个猜测,但我想知道这是否是一个捕获/关闭问题。试试这个:

    public ObservableCollection<PlumFile> FoundFiles
    {
        get
        {
            ObservableCollection<PlumFile> searchResults = new ObservableCollection<PlumFile>();

            // get the data source
            IEnumerable<PlumFile> query = PlumData.GetFiles();

            foreach (FilterConstraint filter in filters)
            {
                var localFilter = filter;
                // debugging
                IList<PlumFile> oldQuery = query.ToList();

                switch (filter.QueryCombiningRule)
                {
                    case FilterConstraint.QueryRule.And:
                        query = query.Where(file => filter.Fits(file));
                        break;
                    case FilterConstraint.QueryRule.Or:
                        query = query.Concat(PlumData.GetFiles().Where(file => localFilter.Fits(file)));
                        break;

                    // is this really how I want to do 'not'?
                    case FilterConstraint.QueryRule.Not:
                        query = query.Where(file => !localFilter.Fits(file));
                        break;
                }

                // debugging
                IList<PlumFile> currQuery = query.ToList();

            }

            query = query.Distinct();

            foreach (PlumFile file in query)
            {
                searchResults.Add(file);
            }

            return searchResults;
        }
    }

答案 1 :(得分:1)

从表面上看,我建议将过滤器应用为急切评估(不是懒惰)。

在loop + make“查询”列表中应用所有过滤器后使用.ToList()。 如果这不起作用,那么你也需要发布“Fits”方法。