LINQ-to-Objects - What's wrong with this simple Composite Key grouping?
Ok guys... first time posting a question on here. I'm trying to demo a couple features of LINQ and have hit a snag. The following query isn't performing as expected:
Dim peopleByAgeAndName = _
From p In (New PeopleRepository).GetAll
Group By key = New With {p.Age, p.Name} Into Group
Select Group
Here is the very simple PeopleRepository:
Public Class PeopleRepository
Public Function GetAll() As List(Of Person)
Dim people As New List(Of Person)
people.Add(New Person With {.Name = "Test Name #1", .Age = 33})
people.Add(New Person With {.Name = "Test Name #1", .Age = 33})
people.Add(New Person With {.Name = "Test Name #2", .Age = 0})
people.Add(New Person With {.Name = "Test Name #3", .Age = 0})
people.Add(New Person With {.Name = "Test Name #4", .Age = 0})
people.Add(New Person With {.Name = "Test Name #5", .Age = 35})
people.Add(New Person With {.Name = "Test Name #1", .Age = 39})
Return people
End Function
End Class
And here is the even simpler Person class:
Public Class Person
Property Name As String
Property Age As Integer
End Class
Obviously this is all code setup for testing purposes. After executing the peopleByAgeAndName
query, I expect to get 6 grou开发者_如何学编程ps. Each containing one Person object except the group corresponding to "Test Name #1" and an age of 33. No matter what I do, though, I get 7 groups of one element each.
Any thoughts? I'm wondering if this is normal for LINQ-to-Objects? Again, it's all testing code. I'm just trying to better understand how this works. It was my understanding that when using an anonymous object as the key, it should do a property-by-property comparison for the groups. I SHOULD be getting 6 groups, not 7.
Thanks!
Update -
For the record, the query rewritten in C# performs exactly as I expect:
var peopleByAgeAndName =
from p in peopleRepository.GetAll()
group p by new {p.Age, p.Name} into g
select g;
I get 6 groups instead of 7. I also confirmed that the group key is not available in VB but is in C#. Kinda weird.
I found the solution for my contrived situation... in Visual Basic, you have to add the "Key" attribute to any property in an Anonymous Type that can be used to determine uniqueness:
Dim peopleByAgeAndName = _
From p In (New PeopleRepository).GetAll
Group p By k = New With {Key p.Age, Key p.Name} Into g = Group
Select g
Works like a charm now! Thanks for your advice guys!
You need an IEqualityComparer that'll give you distinct objects based on Ids perhaps.
The group key is what you want to group by. You're mixing up group and select:
var grp=from p in persons
group p by p.Name into g
select new {g.Key, Ages=g};
Then you'd iterate over it like this:
foreach(var name in grp)
{
Console.WriteLine(name.Key);
foreach(var age in name)
Console.WriteLine(" "+age.Age);
}
This is very simplistic though, a better grouping would be like:
var grp=from p in persons
group p by p.Name into g
select new {Name=g.Key, Ages=from a in g
select a.Age};
精彩评论