C # приведение к интерфейсу со списком и GroupBy - PullRequest
3 голосов
/ 21 июля 2010

Я немного озадачен тем, как выполнить необходимое приведение в следующем:

public IList<IMyClass> Foo()
{
    IList<IMyClass> foo = SomeQuery(); 

    var result = foo.GroupBy(x => x.bar).Select(x => new MyClass()).ToList();

    // So now I have a List<MyClass> which needs casting as IList<IMyClass>

    return result;
}

использование явного приведения не выполняется во время выполнения. Сообщение об ошибке бесполезно, но я предполагаю, что это может быть связано с GroupBy, поскольку обычно я не ожидаю возникновения проблем с чем-то подобным.

Ответы [ 2 ]

7 голосов
/ 21 июля 2010

Это не имеет ничего общего с 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.

1 голос
/ 21 июля 2010

Вы используете .net 4?

, тогда это легко.просто верните IEnumerable из IMyClass.который поддерживает ковариацию, и поэтому вы можете привести его к базовым типам.

в противном случае.сделай это.

result.Select(i=> (IMyClass)i).ToList();
...