Аннотация Имея реализация IEQUITALICAMPER или переопределить сравнительный по умолчанию для использования различного метода

StackOverflow https://stackoverflow.com/questions/4250381

Вопрос

Я пытаюсь найти отчетливый 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() Либо использует компаратор по умолчанию или пропущенное в сравнении. Я надеялся (я читаю не знаю, если это сделано), чтобы написать сравнительную систему в одном месте и иметь возможность использовать его для всех моих классов, поскольку все они сравнивают то же самое равенство (что сравнивает GUID Собственность каждого класса).

Все мои занятия наследуют от BasePage сорт:

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

public class Author : BasePage

public class BlogPost : BasePage

Мой метод равных реализован в BasePage сравнивает GUID свойство, которое уникально для каждого. Когда я звоню Distinct() на Author Кажется, это не работает. Есть ли способ, которым я могу обернуть компаратор в одном месте и всегда сможете использовать его, а не на то, чтобы написать что-то вроде class AuhorComparer : IEqualityComparer<Auhor> Поскольку бы тогда я должен написать то же самое для каждого класса, каждый раз, когда я хочу использовать Distinct(). Или Могу ли я как-то переопределить компаратор по умолчанию, поэтому мне не нужно ничего проходить Distinct()?

Это было полезно?

Решение

То 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 Тогда лучший маршрут должен реализовать IEquatable на Author тип. Когда не дано явную IEqualityComparer то Distinct и другие методы LINQ в конечном итоге уютно используют IEquatable Реализация на типе. Обычно через EqualityComprare<T>.Default

Другие советы

Переопределенные равны должны работать для вас. Одна вещь, которая может быть неправильной, заключается в том, что GetHashCode не переопределяется рядом с равными, которые должны случиться рамочные руководящие принципы.

Кодекс показывает только основную идею, которую, я надеюсь, будет полезна.

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; }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top