2010-12-02 11 views
1

IEnumerableとLINQに問題があります。おそらく私はそれを完全に理解していないでしょう。LINQでの難易度

私は偽ファイル( "PlumFile")のデータソースといくつかのフィルタを持っています。各フィルターには、引数がそのフィルターに適合するかどうかを決定するFits(PlumFile)があります。各フィルタには、 "and"、 "or"、 "not"のいずれかを示すenumもあります。

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; 
     } 
    } 

私は私が間違ってやっているかわからないんだけど:ここでは

は、私は、クエリにすべてのそれらのフィルタを組み合わせるしようとしている方法です。いくつかのクエリでは、正常に動作します。他の人にとっては失敗します。

私は1つの "と"フィルタを持っていればうまくいきます。次に、すでに選択されているものをフィルタリングしない "not"フィルタを追加しますが、すべて削除されます。どうしてこれなの?

(私は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に正しく変換されていないでしょうか?

+1

Fitsメソッドのコードを含めることはできますか? – Mark

+0

私はこれを見つめて5分を費やしましたが、頭が痛いだけで質問に目が痛いです。 – Contango

+0

@Gravitas:それはLINQを乱用しているのですか?それほど複雑でない方法でこれをどうやって行うことができますか? –

答えて

2

これはちょっと推測しますが、これはキャプチャ/クロージャの問題かどうか疑問に思います。これを試してみてください:

+0

これはどのように違いがありますか? –

+0

まずそれを試してください。もしそうなら、私は理由を説明します。 – BFree

+0

@Rosarch:Where句のラムダ式は、フィルタループ変数を参照します。コンパイラはフィルタループ変数への参照を取得しますが、参照時の値は取得しません。それらのラムダが後で評価されるとき(LINQ lazy eval、通常は次の変換ToList())、フィルタループ変数は、参照が行われた時とはおそらく異なります。ループ変数をローカル変数に代入し、ローカル変数をlambdasで使用すると、コンパイラはループ変数への参照だけでなく、現在の値を取得します。 – dthorpe

1

私は、フィルタを熱心な評価(怠け者ではない)として適用することをお勧めします。

ループ内にすべてのフィルタを適用した後に.ToList()を使用すると、「クエリ」リストが作成されます。 それでも問題が解決しない場合は、「適合」方法も投稿する必要があります。

+0

私は 'Fits()'を投稿しました。 –