C#转换为与List和GroupBy的接口

fea*_*net 3 c# linq-to-objects casting group-by interface

我对以下如何进行必要的演员表示感到有点困惑:

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;
}
Run Code Online (Sandbox Code Playgroud)

使用显式转换在运行时失败.错误消息没有用,但我猜它可能与GroupBy有关,因为我通常不希望这样的事情有任何问题.

Jon*_*eet 7

这与之无关GroupBy- 因为它IList<T>是不变的.如果你投出List<MyClass>IList<IMyClass>那么调用者可以再加入这实现了一个类型的实例IMyClass,但不是一个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;
}
Run Code Online (Sandbox Code Playgroud)

这意味着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;
}
Run Code Online (Sandbox Code Playgroud)

或者在Select lambda表达式中执行强制转换:

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

    var result = foo.GroupBy(x => x.bar)
                    .Select(x => (IMyClass) new MyClass())
                    .ToList();
    return result;
}
Run Code Online (Sandbox Code Playgroud)

编辑:为Select失败道歉.你必须同时指定来源和结果,这有点令人讨厌,但没有简单的方法来解决这个问题:(鉴于涉及的丑陋,你可能最好用Cast.