الخلاصة تطبيق iequalitycomparer أو تجاوز المقارن الافتراضي لاستخدام طريقة متميزة

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

نصائح أخرى

يجب أن يعمل Overriden يساوي من أجلك. شيء واحد قد يحدث خطأ هو أن 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