It's nothing to do with GroupBy
- it's because IList<T>
is invariant. If you could cast a List<MyClass>
to IList<IMyClass>
then the caller could then add an instance of a type which implemented IMyClass
but wasn't a MyClass
. (I usually think of this in terms of real world objects: a bunch of bananas isn't a fruit bowl: you can add an apple to a fruit bowl, but not to a bunch of bananas.)
The simplest way would be to manually specify the type in the Select clause:
public IList<IMyClass> Foo()
{
IList<IMyClass> foo = SomeQuery();
var result = foo.GroupBy(x => x.bar)
.Select<IGrouping<IMyClass, Bar>>, IMyClass>(x => new MyClass())
.ToList();
return result;
}
This means result
will actually be a List<IMyClass>
. I don't know the type of item within foo
which makes it tricky to give it in more detail - given your comment, I'll assume that that's IMyClass
, and that x.bar is of type Bar
.
Another alternative (which would be more useful if you wanted to use a query expression for the group/select part) would be to use Cast
:
public IList<IMyClass> Foo()
{
IList<IMyClass> foo = SomeQuery();
var result = foo.GroupBy(x => x.bar)
.Select(x => new MyClass())
.Cast<IMyClass>()
.ToList();
return result;
}
Or perform the cast within the Select lambda expression itself:
public IList<IMyClass> Foo()
{
IList<IMyClass> foo = SomeQuery();
var result = foo.GroupBy(x => x.bar)
.Select(x => (IMyClass) new MyClass())
.ToList();
return result;
}
EDIT: Apologies for the Select
failure. It's somewhat annoying that you have to specify both the source and the result, but there's no easy way of fixing that :( Given the ugliness involved, you may well be best off with Cast
.