bdaniel7
bdaniel7

Reputation: 197

Grouping by anonymous v.s. grouping by non-anonymous

I need to group some data after it has arrived from server.

var result = context.GetData();

Assert.Equal(54, result.Count); // OK

var transactions = result.GroupBy(t => new //BeneficiaryGroup
                        {
                            BankAcronym = t.BankAcronym.Substring(4, 4),
                            DebitDate = t.DebitDate,
                            Key = t.Key
                        })
                    .OrderBy(g => g.Key.BankAcronym)
                    .ThenBy(g => g.Key.DebitDate)
                    .ThenBy(g => g.Key.Key)
                    .ToList();

Assert.Equal( 14, transactions.Count ); // OK

When I'm grouping by an anonymous object, the grouping is correctly done.

When I'm grouping by a BeneficiaryGroup object, with the exact same properties

public class BeneficiaryGroup 
{ 
    BankAcronym,
    DebitDate,
    Key
}

the grouping is not correctly done - the group has 54 records, as before grouping.

And I want to group the data by a class so I can return to the API consumer a collection already grouped.

Any ideas why this strange behaviour?

Upvotes: 3

Views: 80

Answers (1)

AakashM
AakashM

Reputation: 63378

Anonymous types get 'sensible' equality behaviour 'for free', which is why the grouping works as you expect in that case. When you switch to using a named class, it then becomes your responsibility as the class definer to provide equality behaviour, to allow a BeneficiaryGroup to be used as a grouping key in the manner you expect.


As it says in the docs for GroupBy,

The default equality comparer Default is used to compare keys.

where Default is EqualityComparer<T>.Default, which explains:

The Default property checks whether type T implements the System.IEquatable<T> interface and, if so, returns an EqualityComparer<T> that uses that implementation. Otherwise, it returns an EqualityComparer<T> that uses the overrides of Object.Equals and Object.GetHashCode provided by T.

And for an anonymous type,

Because the Equals and GetHashCode methods on anonymous types are defined in terms of the Equals and GetHashCode methods of the properties, two instances of the same anonymous type are equal only if all their properties are equal.

whereas for a named type that doesn't override Equals and GetHashCode, you will get the Object implementations, which generally aren't useful.

Upvotes: 1

Related Questions