Abstrakt ein IEqualityComparer Implementierung oder den Standardvergleich außer Kraft setzen Distinct-Methode zu verwenden

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

Frage

Ich versuche, eine deutliche List<Author> ein List<BlogPost> gegeben zu finden, wo jeder BlogPost eine Author Eigenschaft hat. Ich habe die Distinct() Erweiterungsmethode in den Bereichen Generika gefunden und ich versuche, es zu benutzen. Erstens, lassen Sie mich erklären meine Schleife und wo ich es benutzen wollen, dann werde ich meine Klassen erklären und wo ich habe Probleme.

Der Versuch, unterschiedliche verwenden hier

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

Nach dem, was ich habe lesen auf MSDN , Distinct() entweder verwendet den Standardvergleich oder ein in comparer geben. Ich hatte gehofft, (I obviosuly weiß nicht, ob dies machbar ist) einen Vergleich an einer Stelle zu schreiben und in der Lage sein, es für all meine Klassen zu verwenden, da sie alle von der exakt gleichen Gleichheit Vergleichsoperation (die die GUID Eigenschaft vergleicht die jede Klasse).

Alle meine Klassen erben von der BasePage Klasse:

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

public class Author : BasePage

public class BlogPost : BasePage

entspricht Meine Methode in BasePage implementiert, um die GUID Eigenschaft vergleicht, die zu jeder einzigartig ist. Als ich Distinct() auf einem Author nennen scheint es nicht zu arbeiten. Gibt es eine Möglichkeit, die comparer an einem Ort einpacken kann und immer in der Lage sein, es zu benutzen, anstatt wie class AuhorComparer : IEqualityComparer<Auhor> zu schreiben etwas mit, da ich dann bräuchten, um die gleiche Sache für jede Klasse schreibt jedes Mal, ich will Distinct() verwenden . oder kann ich den Standardvergleich irgendwie außer Kraft setzen, so muß ich nichts zu Distinct() passieren?

War es hilfreich?

Lösung

Die Distinct Operation ist wahrscheinlich nicht die beste Lösung, weil man hier nur eine potenziell sehr große Liste mit Dubletten Gebäuden am Ende, um dann sofort schrumpfen sie verschiedene Elemente. Es ist wahrscheinlich besser, nur mit einem HashSet<Author> zu beginnen, die großen Liste zu vermeiden aufzubauen.

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

Wenn Sie verwenden möchten Distinct tun, dann ist die beste Route IEquatable auf dem Author Typ zu implementieren. Wenn kein expliziten IEqualityComparer der Distinct und andere LINQ Methoden gegeben werden standardmäßig schließlich in der Art der IEquatable Implementierung verwenden. In der Regel durch EqualityComprare<T>.Default

Andere Tipps

außer Kraft setzen Equals sollte für Sie arbeiten. Eine Sache, die schief gehen könnte, ist, dass GetHashCode nicht neben Equals überschrieben wird, die die Rahmenrichtlinien vorschreiben passieren sollte.

Der Code zeigt nur die Hauptidee, die, wie ich hoffe, nützlich sein wird.

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; }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top