У меня есть этот класс
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 в качестве параметра, но существует ли эквивалентное использование пункта группы? Я делаю что-то не так?? Какие-либо мысли?
Вы показали реализацию Equals, но не GetHashCode. Вам нужно переопределить оба (и согласованным образом), чтобы группировка работала.
Пример реализации GetHashCode:
public override int GetHashCode()
{
int hash = 23;
hash = hash * 31 + Latitude.GetHashCode();
hash = hash * 31 + Longitude.GetHashCode();
return hash;
}
Обратите внимание, что сравнение значений float
на предмет точного равенства всегда несколько рискованно, но я, по крайней мере, ожидал, что ваши модульные тесты пройдут успешно, учитывая, что они не выполняют никаких расчеты.
Существует перегрузка метода GrouBy , который принимает IEqualityComparer в качестве параметра, но существует ли эквивалент с использованием предложения group?
Вы всегда можете группа по анонимному типу, если вам просто нужно быстрое встроенное решение и вы не беспокоитесь о точном вводе ключей:
var grouped =
from it in items
group it by new {it.Coordinate.Latitude, it.Coordinate.Longitude};