Reputation: 2783
I've following data
Id1 Id2 Days
------------------------
1 1 10
1 1 20
1 2 30
1 3 40
I want to group data by the Id1
and Id2
using Linq
When I do the group by as below it gives me correct result
List<data>.GroupBy(p => new {p.Id1, p.Id2});
But when I use the predefined type it gives me result as four different row groups. It doesn't combine the first 2 rows in a single group.
List<data>.GroupBy(p => new GroupKey(p.Id1, p.Id2));
class GroupKey
{
public GroupKey(decimal _id1,decimal _id2)
{
Id1= _id1;
Id2= _id2;
}
public decimal Id1{ get; set; }
public decimal Id2{ get; set; }
}
How to achieve the same result with predefined type?
Upvotes: 1
Views: 97
Reputation: 12849
Use struct
instead of class
and make it immutable.
struct GroupKey
{
public GroupKey(decimal _id1,decimal _id2):this()
{
Id1= _id1;
Id2= _id2;
}
public decimal Id1{ get; private set; }
public decimal Id2{ get; private set; }
}
First, it will take less memory than class. And second, the default struct equality behavior compares content of the structure and not reference. Which is why it is not grouping properly.
Upvotes: 1
Reputation: 126072
Implement Equals
and GetHashCode
for the type.
Something like:
public override bool Equals(object other)
{
var otherKey = other as GroupKey;
if (otherKey == null)
{
return false;
}
return otherKey.Id1 == this.Id1 && otherKey.Id2 == this.Id2;
}
public override int GetHashCode()
{
return this.Id1.GetHashCode() ^ this.Id2.GetHashCode();
}
The reason this works for anonymous types (like the one you created in the first example) is because anonymous types automatically get an implementation of Equals
and GetHashCode
that are defined in terms of the properties defined on the anonymous type (See the "remarks" section on the "Anonymous Types" article on MSDN).
Upvotes: 4