gmail user
gmail user

Reputation: 2783

GroupBy with predefined type using Linq

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

Answers (2)

Euphoric
Euphoric

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

Andrew Whitaker
Andrew Whitaker

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

Related Questions