Это не имеет ничего общего с GroupBy
- это потому, что IList<T>
является инвариантом. Если вы могли бы привести List<MyClass>
к IList<IMyClass>
, тогда вызывающая сторона может добавить экземпляр типа, который реализовал IMyClass
, но не был a MyClass
. (Я обычно думаю об этом с точки зрения объектов реального мира: гроздь бананов - это не ваза с фруктами: ты можешь добавить яблоко в вазу с фруктами, но не в гроздь бананов.)
Самый простой способ - указать тип вручную в предложении Select:
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;
}
Это означает, что result
на самом деле будет List<IMyClass>
. Я не знаю тип элемента в foo
, что затрудняет подробное его описание - учитывая ваш комментарий, я предполагаю, что это IMyClass
, а x.bar типа Bar
.
Другой альтернативой (которая была бы более полезна, если вы хотите использовать выражение запроса для группы / части выбора) было бы использование 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;
}
Или выполнить приведение внутри самого выражения лямбда-выражения:
public IList<IMyClass> Foo()
{
IList<IMyClass> foo = SomeQuery();
var result = foo.GroupBy(x => x.bar)
.Select(x => (IMyClass) new MyClass())
.ToList();
return result;
}
РЕДАКТИРОВАТЬ: Извинения за сбой Select
. Немного раздражает, что вам нужно указывать и источник, и результат, но не существует простого способа исправить это :( Учитывая уродство, вам лучше всего использовать Cast
.