简体   繁体   English

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

[英]C# cast to interface with List and GroupBy

I'm a bit stumped about how to perform the necessary cast in the following: 我对以下如何进行必要的演员表示感到有点困惑:

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;
}

using an explicit cast fails at run time. 使用显式转换在运行时失败。 The error message isn't helpful but I'm guessing it maybe something to do with the GroupBy as I wouldn't normally expect to have any problem with something like this. 错误消息没有用,但我猜它可能与GroupBy有关,因为我通常不希望这样的事情有任何问题。

It's nothing to do with GroupBy - it's because IList<T> is invariant. 它与GroupBy无关 - 这是因为IList<T>是不变的。 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 . 如果你可以List<MyClass>IList<IMyClass>那么调用者可以添加一个实现IMyClass不是 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: 最简单的方法是在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;
}

This means result will actually be a List<IMyClass> . 这意味着result实际上是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 . 我不知道foo中的项目类型使得更详细地给它变得棘手 - 鉴于你的评论,我将假设那 IMyClass ,而x.bar是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 : 另一种选择(如果你想为组/选择部分使用查询表达式会更有用)将是使用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: 或者在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;
}

EDIT: Apologies for the Select failure. 编辑:为Select失败道歉。 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 . 有点烦人的是你必须同时指定源和结果,但是没有简单的方法来解决这个问题:(鉴于涉及的丑陋,你可能最好使用Cast

Do you use .net 4? 你用.net 4吗?

then its easy. 那很容易。 just return an IEnumerable of IMyClass. 只返回一个IEnumerable的IMyClass。 that supports covariance, and therefore you can cast it to base types. 支持协方差,因此您可以将其转换为基类型。

otherwise. 除此以外。 do this. 做这个。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM