Reputation: 85
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
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
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