1

我试图找到一个不同的List<Author>给定一个List<BlogPost>,每个BlogPost都有一个Author属性。我Distinct()在泛型中找到了扩展方法,我正在尝试使用它。首先,让我解释一下我的循环以及我想在哪里使用它,然后我将解释我的类以及我遇到问题的地方。

尝试在这里使用 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()要么使用默认比较器,要么使用传入的比较器。我希望(我显然不知道这是否可行)在一个地方编写一个比较器并能够将它用于我的所有类,因为它们都通过完全相同的相等操作进行比较(比较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它似乎不起作用。有什么办法可以将比较器包装在一个地方并始终能够使用它,而不必编写类似的东西,class AuhorComparer : IEqualityComparer<Auhor>因为我需要为每个类编写相同的东西,每次我想使用Distinct(). 或者我可以以某种方式覆盖默认比较器,这样我就不必传递任何东西了Distinct()

4

3 回答 3

2

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那么最好的方法是IEquatableAuthor类型上实现。如果没有给出明确IEqualityComparer的 theDistinct和其他 LINQ 方法,最终将默认使用IEquatable该类型的实现。通常通过EqualityComprare<T>.Default

于 2010-11-22T21:35:46.473 回答
0

Overriden Equals 应该适合你。可能出错的一件事是 GetHashCode 没有与 Equals 一起被覆盖,框架指南规定应该发生这种情况。

于 2010-11-22T21:34:54.303 回答
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; }
}
于 2010-11-22T22:16:55.127 回答