2010-11-22 10 views
0

List<BlogPost>という別個のList<Author>を見つけようとしています。それぞれBlogPostAuthorというプロパティがあります。私はジェネリックスでDistinct()拡張メソッドを見つけました。私はそれを使用しようとしています。まず、私のループを説明してみましょう。どこで使用したいのですか?私のクラスとどこに問題があるのか​​を説明します。私はread on MSDNDistinct()いずれかが既定の比較や比較演算子に渡さ使用してきたものに基づいて、ここで要約IEqualityComparer実装を使用するか、デフォルトのコンペアを使用してDistinctメソッドをオーバーライドします。

public List<Author> GetAuthors() { 

    List<BlogPost> posts = GetBlogPosts(); 
    var authors = new List<Author>(); 

    foreach (var bp in posts) { 
    authors.Add(bp.Author); 
    } 

    return authors.Distinct().ToList(); 
} 

を明確な使用しようと

。私はのGUID性質を比較した(1つのスポットで比較子を書き、それらはすべてがまったく同じ平等操作により比較するので、私のクラスのすべてのためにそれを使用できるようにする(これはなんとかであれば、私はobviosuly知らない)期待していました各クラス)。

私のクラスのすべてのBasePageクラスから継承:

public class BasePage : System.Web.UI.Page, IBaseTemplate, IEquatable<IBaseTemplate>, IEqualityComparer<IBaseTemplate> 

public class Author : BasePage 

public class BlogPost : BasePage 

私はBasePageに実装された方法は、それぞれに固有のGUIDプロパティを比較し等しいです。私がAuthorDistinct()を呼び出すと、うまくいかないようです。私は1つの場所で比較演算子をラップし、常に、むしろ私はその後、各クラスの同じことを記述する必要があると思いますので、class AuhorComparer : IEqualityComparer<Auhor>ような何かを書くことよりも、私はDistinct()を使用するたびにそれを使用することができる方法はあります。 デフォルトコンバーターを何とかオーバーライドできますので、Distinct()に何も渡す必要はありませんか?

答えて

2

Distinct操作は、おそらくここでは最良の解決策ではありません。大きなリストの作成を避けるには、HashSet<Author>から始める方がいいでしょう。

public List<Author> GetAuthors() { 
    HashSet<Author> authorSet = new HashSet<Author>(); 
    foreach (var author in GetBlogPosts().Select(x => x.Author)) { 
    authorSet.Add(author); 
    } 
    return authorSet.ToList(); 
} 

あなたがDistinctを使いたいんなら、最適なルートはAuthorタイプにIEquatableを実装することです。明示的にIEqualityComparerが指定されていない場合、Distinctと他のLINQメソッドは、最終的にはそのタイプに対してIEquatable実装を使用するようにデフォルト設定されます。通常EqualityComprare<T>.Default

+0

HashSetの提案に感謝します。私はあなたの変更を実装しましたが、私はまだ同じサイズのリストを取得します。私は記事の3つのリストを持っている、2つは同じ著者を持って、1つは全く異なる著者を持っています。私は3人の著者のリストを得る。 –

+0

HashSetに同じ著者が含まれているという事実が、私のEqualsメソッドとGetHashCodeメソッドが正しく書かれていないことを複数回証明していますか? –

+0

私の 'GetHashCode'メソッドが正しく書かれていないので、これがうまくいかないことを確認しました。今私はこのアプローチを 'HashSet'の働きで行っています。ありがとう! –

0

オーバーライドさ等号はあなたのために働く必要があります。間違っているかもしれないことの1つは、GetHashCodeがEqualsと並行してオーバーライドされないということです。あなただけにして、すぐに明確な要素にそれを縮小するために、重複して潜在的に非常に大きなリストを構築してしまうので

0

コードを通じてのみ、私は願って、有用であろう主なアイデアを、示しています。

public class Repository 
{ 
    public List<Author> GetAuthors() 
    { 
     var authors = new List<Author> 
         { 
          new Author{Name = "Author 1"}, 
          new Author{Name = "Author 2"}, 
          new Author{Name = "Author 1"} 
         }; 
     return authors.Distinct(new CustomComparer<Author>()).ToList(); 
    } 

    public List<BlogPost> GetBlogPosts() 
    { 
     var blogPosts = new List<BlogPost> 
     { 
      new BlogPost {Text = "Text 1"}, 
      new BlogPost {Text = "Text 2"}, 
      new BlogPost {Text = "Text 1"} 
     }; 
     return blogPosts.Distinct(new CustomComparer<BlogPost>()).ToList(); 
    } 
} 

//This comparer is required only one. 
public class CustomComparer<T> : IEqualityComparer<T> where T : class 
{ 
    public bool Equals(T x, T y) 
    { 
     if (y == null && x == null) 
     { 
      return true; 
     } 
     if (y == null || x == null) 
     { 
      return false; 
     } 
     if (x is Author && y is Author) 
     { 
      return ((Author)(object)x).Name == ((Author)(object)y).Name; 
     } 
     if (x is BlogPost && y is BlogPost) 
     { 
      return ((BlogPost)(object)x).Text == ((BlogPost)(object)y).Text; 
     } 
     //for next class add comparing logic here 
     return false; 
    } 

    public int GetHashCode(T obj) 
    { 
     return 0; // actual generating hash code should be here 
    } 
} 

public class Author 
{ 
    public string Name { get; set; } 
} 

public class BlogPost 
{ 
    public string Text { get; set; } 
} 
関連する問題