Given a collection of players that were constructed like this:
private static IList<Player> LoadPlayers()
{
Player favre = new Player { Id = 1, Name = "Favre", Team = new Team { Id = 1, Name = "Vikings" } };
Player peterson = new Player { Id = 2, Name = "Peterson", Team = new Team { Id = 1, Name = "Vikings" } };
Player rodgers = new Player { Id = 3, Name = "Rodgers", Team = new Team { Id = 2, Name = "Packers" } };
Player driver = new Player { Id = 4, Name = "Driver", Team = new Team { Id = 2, Name = "Packers" } };
List<Player> players = new List<Player> {favre, peterson, rodgers, driver};
return players;
}
And the following LINQ query:
var query =
from p in LoadPlayers()
group p by p.Team into g
select g;
We will see the following output:
Vikings
Vikings
Packers
Packers
The reason this is happening is that we created new Team objects for each and every Player, and when LINQ tries to group, it does so based on object equality. The solution to this is to
override the Equals() and GetHashCode() methods in the Team class. After doing that, the LINQ query will be able to group the objects up properly and just display each team name once.
Resharper has a nice code generation template to create solid implementations of these methods (press Alt+Ins to bring up the code generation menu).
The example here is obviously contrived. We could create each team object once, and then use the same instance during the property assignment, and if we did that, things would work just fine. However, I ran into a more generalized version of this problem when using WCF and a lot of custom code generation. The underlying lesson is still the same: LINQ and GroupBy need to have object equality defined properly in order to make things work as you would expect.