Damien7792
Damien7792

Reputation: 85

Linq - Using GroupBy with my own type vs anonymous type

I have a list of objects I want to group with Linq. The objects type is GroupRating. I want to group them by their "Params" property.

public class GroupRating
{
    public long Id { get; set; }
    public Parameters Params { get; set; }
}

public class Parameters
{
    public int CarrierId { get; set; }
    public int CustomerId { get; set; }
}

The thing is that this works: (ie. I get only one group with all the ids)

        var myList = new List<GroupRating>();
        ... blahblah code...

        var groupedList = myList.GroupBy(i => new {
             CarrierId = i.Params.CarrierId,
             CustomerId = i.Params.CustomerId
         }, i => i.Id).ToArray();

But this doesn't work: (ie. I get as many groups as there is Ids)

        var myList = new List<GroupRating>();
        ... blahblah code...

        var groupedList = myList.GroupBy(i => new Params {
             CarrierId = i.Params.CarrierId,
             CustomerId = i.Params.CustomerId
         }, i => i.Id).ToArray();

Any idea why?

Thanks

Upvotes: 5

Views: 1429

Answers (2)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 62002

Your class must override Equals(object) and GetHashCode() correctly. Otherwise two new Params { ... } will not be "equal" even if they look the same.

Anonymous types override these two methods automatically.

You could also use a struct instead of a class because a struct uses the overrides of Equals(object) and GetHashCode() that exist in System.ValueType. If you choose a struct, consider making the type immutable, i.e. make the properties read-only (or with private set;).


Later addition: Starting in 2020 (C# 9), you should use a record type if you want to make it easy for yourself. Then the C# compiler automatically generates Equals(object) and GetHashCode() implementations for you that match your exact needs in each case (no reflection). Since 2021 (C# 10), you can also choose record struct if you want a value-type record.

Upvotes: 10

hakantopuz
hakantopuz

Reputation: 511

You must use class or anonymous type.Params is not class.You can use it.

Try this:

  var groupedList = myList.GroupBy(i => new Parameters {
                 CarrierId = i.CarrierId,
                 CustomerId = i.CustomerId
             }, i => i.Id).ToArray();

Upvotes: 0

Related Questions