Using Distinct with LINQ and Objects

Существует «sprintf» для JavaScript, который вы можете найти на http://www.webtoolkit.info/javascript-sprintf.html .

16
задан Ray Booysen 14 December 2010 в 12:08
поделиться

1 ответ

Я знаю, что это - старый вопрос, но я не удовлетворен ни одним из ответов. Я занял время для понимания этого для меня, и я хотел совместно использовать свои результаты.

Первый важно считать и понять эти две вещи:

  1. история IEqualityComparer
  2. EqualityComparer

Long, короткая для создания .Distinct(), расширение понимает, как определить равенство объекта - необходимо определить "EqualityComparer" для объекта T. При чтении документов Microsoft, это буквально указывает:

Мы рекомендуем произойти из класса EqualityComparer вместо того, чтобы реализовать интерфейс IEqualityComparer...

, Именно так Вы определяете, что использовать, потому что это уже было решено для Вас.

Для .Distinct() расширение для работы успешно необходимо удостовериться, что объекты могут быть сравнены точно. В случае .Distinct() GetHashCode() метод - то, что действительно имеет значение.

можно проверить это для себя путем записи GetHashCode() реализация, которая просто возвращает текущий Хэш-код объекта, передаваемого в, и Вы будете видеть, что результаты плохи, потому что это значение изменяется на каждом выполнении. Это делает Ваши объекты слишком уникальными, который является, почему важно на самом деле записать надлежащую реализацию этого метода.

Ниже точная копия примера кода от IEqualityComparer<T> страница с данными тестирования, маленькой модификацией к GetHashCode() метод и комментирует для демонстрации точки.

//Did this in LinqPad
void Main()
{
    var lst = new List<Box>
    {
        new Box(1, 1, 1),
        new Box(1, 1, 1),
        new Box(1, 1, 1),
        new Box(1, 1, 1),
        new Box(1, 1, 1)
    };

    //Demonstration that the hash code for each object is fairly 
    //random and won't help you for getting a distinct list
    lst.ForEach(x => Console.WriteLine(x.GetHashCode()));

    //Demonstration that if your EqualityComparer is setup correctly
    //then you will get a distinct list
    lst = lst
        .Distinct(new BoxEqualityComparer())
        .ToList();

    lst.Dump();
}

public class Box
{
    public Box(int h, int l, int w)
    {
        this.Height = h;
        this.Length = l;
        this.Width = w;
    }

    public int Height { get; set; }
    public int Length { get; set; }
    public int Width { get; set; }

    public override String ToString()
    {
        return String.Format("({0}, {1}, {2})", Height, Length, Width);
    }
}

public class BoxEqualityComparer 
    : EqualityComparer<Box>
{
    public override bool Equals(Box b1, Box b2)
    {
        if (b2 == null && b1 == null)
            return true;
        else if (b1 == null || b2 == null)
            return false;
        else if (b1.Height == b2.Height && b1.Length == b2.Length
                            && b1.Width == b2.Width)
            return true;
        else
            return false;
    }

    public override int GetHashCode(Box bx)
    {
        #region This works
        //In this example each component of the box object are being XOR'd together
        int hCode = bx.Height ^ bx.Length ^ bx.Width;

        //The hashcode of an integer, is that same integer
        return hCode.GetHashCode();
        #endregion

        #region This won't work
        //Comment the above lines and uncomment this line below if you want to see Distinct() not work
        //return bx.GetHashCode();
        #endregion
    }
}
0
ответ дан 30 November 2019 в 17:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: