开发者

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&g开发者_如何学JAVAt;

    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.


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.


Do you use .net 4?

then its easy. just return an IEnumerable of IMyClass. that supports covariance, and therefore you can cast it to base types.

otherwise. do this.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜