Как сгруппироваться пользовательскими типами с linq

У меня есть этот класс

public class Item
{
       public Coordinate coordinate { get; set; }
        ...
        ...
}

Так как Координата, определяют как это:

public class Coordinate
{
        public Coordinate(float latitude, float longitude)
        {
            Latitude = latitude;
            Longitude = longitude;
        }

        public float Latitude { get; private set; }
        public float Longitude { get; private set; }
}

И я хочу иметь запрос linq как этот:

var grouped = from it in items
              group it by it.Coordinate into grp
              select grp;

Как упомянуто здесь MSDN я думал, что это было возможно, если я переопределю, Равняется на моем Координатном классе:

Используйте именованный тип, если необходимо передать переменную запроса другому методу. Создайте специальный класс с помощью автореализованных свойств для ключей и затем переопределите методы Равняний и GetHashCode. Можно также использовать структуру, в этом случае Вы не должны строго переопределять те методы. Для получения дополнительной информации посмотрите Как к: Реализуйте Неизменный Класс, Который Автореализовал Свойства

Равняется реализации для Координатного класса:

public override bool Equals(object obj)
{
       var coord = obj as Coordinate;
       if(coord == null) return false;
       return (Latitude == coord.Latitude && Longitude == coord.Longitude);
}

тем не менее я не могу заставить свой запрос linq группироваться подобными координатами как мои провальные тестовые шоу:

[TestMethod]
public void GroupBy_3ItemsWith2DifferentCoordinates_Returns2Groups()
{
    var items = new List
        {
            new Item {Coordinate = new Coordinate(10, 10)},
            new Item {Coordinate = new Coordinate(10, 10)},
            new Item {Coordinate = new Coordinate(12, 10)},
        };
    var grouped = from it in items
                  group it by it.Coordinate into g
                  select g;
    Assert.AreEqual(2, grouped.Count());
}

Существует перегрузка к методу GrouBy, который берет IEqualityComparer в качестве параметра, но существует ли эквивалентное использование пункта группы? Я делаю что-то не так?? Какие-либо мысли?

12
задан Stéphane 17 February 2010 в 11:29
поделиться

2 ответа

Вы показали реализацию Equals, но не GetHashCode. Вам нужно переопределить оба (и согласованным образом), чтобы группировка работала.

Пример реализации GetHashCode:

public override int GetHashCode()
{
    int hash = 23;
    hash = hash * 31 + Latitude.GetHashCode();
    hash = hash * 31 + Longitude.GetHashCode();
    return hash;
}

Обратите внимание, что сравнение значений float на предмет точного равенства всегда несколько рискованно, но я, по крайней мере, ожидал, что ваши модульные тесты пройдут успешно, учитывая, что они не выполняют никаких расчеты.

23
ответ дан 2 December 2019 в 06:08
поделиться

Существует перегрузка метода GrouBy , который принимает IEqualityComparer в качестве параметра, но существует ли эквивалент с использованием предложения group?

Вы всегда можете группа по анонимному типу, если вам просто нужно быстрое встроенное решение и вы не беспокоитесь о точном вводе ключей:

var grouped =
  from it in items 
  group it by new {it.Coordinate.Latitude, it.Coordinate.Longitude};
2
ответ дан 2 December 2019 в 06:08
поделиться
Другие вопросы по тегам:

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