ICalityCompererの実装を抽象化するか、デフォルトの比較を使用して個別の方法を使用します
-
27-09-2019 - |
質問
私は明確なものを見つけようとしています List<Author>
与えられます List<BlogPost>
それぞれ BlogPost
持っています Author
財産。私はそれを見つけました 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();
}
私が何に基づいていますか MSDNを読んでください, Distinct()
デフォルトの比較を使用するか、比較して渡されます。私は、これが1つの場所で比較を書いて、私のすべてのクラスにそれを使用できることを望んでいました(私は明らかにこれが実行可能かどうかはわかりません)。 GUID
各クラスのプロパティ)。
私のすべてのクラスはから継承します BasePage
クラス:
public class BasePage : System.Web.UI.Page, IBaseTemplate, IEquatable<IBaseTemplate>, IEqualityComparer<IBaseTemplate>
public class Author : BasePage
public class BlogPost : BasePage
私のEqualsメソッドが実装されています BasePage
比較します GUID
それぞれに固有のプロパティ。電話するとき Distinct()
で Author
うまくいかないようです。比較を1か所でまとめて、常に使用することができる方法はありますか class AuhorComparer : IEqualityComparer<Auhor>
それから、クラスごとに同じことを書く必要があるので、私が使用したいたびに Distinct()
. または 何らかの形でデフォルトの比較をオーバーライドできますか? Distinct()
?
解決
Distinct
操作はおそらくここでは最良の解決策ではありません。なぜなら、あなたはそれをすぐに異なる要素に縮小するためだけに、複製するだけで潜在的に非常に大きなリストを構築することになっているからです。ちょうどaから始める方がおそらく良いでしょう 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
その後、最良のルートは実装することです IEquatable
に Author
タイプ。明示的なものが与えられていない場合 IEqualityComparer
Distinct
および他のLINQメソッドは最終的にデフォルトを使用します IEquatable
タイプの実装。通常は EqualityComprare<T>.Default
他のヒント
Overriden Equalsはあなたのために働くはずです。間違っている可能性のあることの1つは、GethashCodeがEqualsとともにオーバーライドされていないことであり、フレームワークガイドラインが指示するはずです。
コードは主なアイデアのみを示していますが、これが役立つことを願っています。
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; }
}