我在使用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?
答案 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”方法。