Reputation: 159
I have a linq expression that I want to group and and cast as hard type List<DocumentGroup>
This linq query works correctly:
var DocumentGroups = (from dt in DocumentTypes
let dg = dt.DocumentGroup
select new DocumentGroup(){
Name = dg.Namn,
Id = dg.Id
}).GroupBy(group => group.Id).ToList();
Now I want do the same query and cast it to a List<DocumentGroup>
but I receive this error:
Unable to cast object of type 'Grouping[System.Guid,ConsoleApplication1+DocumentGroup]' to type 'DocumentGroup'.
List<DocumentGroup> DocumentGroups = (from dt in DocumentTypes
let dg = dt.DocumentGroup
select new DocumentGroup(){
Name = dg.Namn,
Id = dg.Id
}).GroupBy(group => group.Id).Cast<DocumentGroup>.ToList();
If I remove .GroupBy(group => group.Id)
from the linq expression, it works correctly, but I need the group expression to filter it out. How can I make this work?
The DocumentGroup class
public class DocumentGroup
{
public string Name { get; set; }
public Guid Id { get; set; }
}
Upvotes: 1
Views: 1435
Reputation: 1
Before doing the GroupBy
you have a list of DocumentGroup
(like single dimensional array)
1 Name1 <record 1 of DocumentGroup>
1 Name2 <record 2 of DocumentGroup>
1 Name3 <record 3 of DocumentGroup>
2 Name4 <record 4 of DocumentGroup>
3 Name5 <record 5 of DocumentGroup>
After doing the GroupBy
you have a list of IGrouping<int, DocumentGroup>
(like a two dimensional array)
1 1 Name1 --|
1 Name2 -- <record 1 of IGrouping<int, DocumentGroup>
1 Name3 --|
2 2 Name4 <record 2 of IGrouping<int, DocumentGroup>>
3 3 Name5 <record 3 of IGrouping<int, DocumentGroup>>
So to get the DocumentGroup
you need to access from the Grouping
item first, then you get the DocumentGroup
, example:
var groupOfDocumentGroups = /* omitted code */
select new DocumentGroup() { Name = dg.Namn, Id = dg.Id })
.GroupBy(group => group.Id)
.ToList();
foreach(var groupItem in groupOfDocumentGroups)
{
// groupItem type is IGrouping<int, DocumentGroup>
// groupItem has `Key` property which is an integer of the Id.
// groupItem is also a collection that you can do enumeration.
foreach(var item in groupItem)
{
// there you go, item type is DocumentGroup
}
}
but I must have the group expression to filter it out
I assume you want to get all unique DocumentGroup
s in all DocumentType
s, then Salman22
answer is what you're looking for.
You can also use Distinct
in this case. If you're working with linq to entities, you can just have.
var documentGroups = context.DocumentTypes
.Select(x => x.DocumentGroup)
.Distinct()
.ToList();
If you're working with linq to object, you can implement IEqualityComparer<DocumentGroup>
first.
class DocumentGroupComparer : IEqualityComparer<DocumentGroup>
{
public bool Equals(DocumentGroupx, DocumentGroupy)
{
return x.Id == y.Id;
}
public int GetHashCode(DocumentGroup obj)
{
return obj.Id.GetHashCode();
}
}
var documentGroups = DocumentTypes
.Select(x => x.DocumentGroup)
.Distinct(new DocumentGroupComparer())
.ToList();
Upvotes: 0
Reputation: 101681
When you use GroupBy
you get groups. So casting a group to a single item will fail.
If all you want to do is remove duplicates then you can select the first item from each group:
var DocumentGroups = (from dt in DocumentTypes
let dg = dt.DocumentGroup
select new DocumentGroup()
{
Name = dg.Namn,
Id = dg.Id
}).GroupBy(group => group.Id)
.Select(g => g.First())
.ToList();
Upvotes: 4