Объект в условии GROUP BY в C# LINQ - некорректная группировка, если использовать не анонимный тип
Есть тестовый список пользователей:
public class ClassForOrderBy
{
public string Name { get;set; }
public int Priority { get;set; }
public long OwnerId { get;set; }
public ClassForOrderBy(string name, int priority, int ownerId)
{
Name = name;
Priority = priority;
OwnerId = ownerId;
}
}
List<ClassForOrderBy> t = new List<ClassForOrderBy>()
{
new ClassForOrderBy("Иван",14,5),
new ClassForOrderBy("Маша",27,6),
new ClassForOrderBy("Маша",97,7),
new ClassForOrderBy("Иван",60,8)
};
Так же есть тип для группировки (далее в этом типе будут добавляться свойства и заполняться по определенному условию, т.е. объект группировки будет меняться, остальные свойства будут null):
private class AdvancedGroupByFilter
{
public string Name { get;set; }
public AdvancedGroupByFilter(string name) => Name = name;
}
Необходимо сгруппировать элементы списка по свойству "Name". Для группировки я использую метод расширения LINQ (GroupBy), но он странно себя ведет:
- если указать анонимный тип
t.GroupBy(x => new {x.Name}), то мы получаем на выходе
- если указать тип BaseGroupByFilter
t.GroupBy(x => new BaseGroupByFilter(x.Name)), то мы получаем на выходе
Анонимные типы мне не подходят, так как далее будут дополнительные условие OrderBy и ThenBy, которые должны знать, объект какого типа использовался в GroupBy. Почему группировка так странно себя ведет и как заставить ее отрабатывать правильно при указании не анонимного типа?
Ответы (1 шт):
Публикую ответ на свой вопрос (возможно, кому-нибудь пригодится).
В комментарии к вопросу tym32167 был прав, когда рекомендовал переопределить методы Equals и GetHashCode. В результате имеем нечто следующее (дополнительно, для наглядности, добавил в тип BaseGroupByFilter свойство OwnerId с типом nullable long):
private class BaseGroupByFilter
{
public string Name { get; }
public long? OwnerId { get; }
public BaseGroupByFilter(string name, long? ownerId = null)
{
Name = name;
OwnerId = ownerId;
}
public override bool Equals(object obj) => Equals(obj as BaseGroupByFilter);
public override int GetHashCode()
{
unchecked
{
var hash = (OwnerId != null ? OwnerId.GetHashCode() : 0);
hash = (hash * 27) ^ Name.GetHashCode();
return hash;
}
}
private bool Equals(BaseGroupByFilter other) =>
other != null && other.Name == this.Name && other.OwnerId == this.OwnerId;
}
Группировка теперь работает корректно:


