How can I convert an object of type IEnumerable <Foo> to IEnumerable <IFoo> if passed to a function as an object?

I am trying to raise a parameter passed as an object (which is an upcast of an object of type IEnumerable) to IEnumerable, where Foo implements IFoo.

Here is an example of what I would like to do, but it doesn't work.

public void F(object o)
{
    //I know the object o is of type IEnumerable<Foo> where Foo implements IFoo
    IEnumerable<IFoo> ifoos = (IEnumerable<IFoo>) o);
}

      

Is there a job? I don't want the F Foo function to be specific, but I cannot get it to pass to the interface, unless I do:

IEnumerable<IFoo> ifoos = (IEnumerable<Foo>) o).Select( f => (IFoo) f);

      

thank

Giuseppe

+2


source to share


2 answers


Before .NET 4.0, you can't - IEnumerable<T>

is invariant until .NET 4.0.

With .NET 4.0, the code you posted will work fine.

In .NET 3.5, you can use Enumerable.Cast

:

public void F(object o)
{
    IEnumerable<IFoo> ifoos = ((IEnumerable) o).Cast<IFoo>();
}

      



It basically uses a weakly typed one IEnumerable

(which extends both IEnumerable<Foo>

and IEnumerable<IFoo>

so the cast would be fine) and then applies a method Cast<T>

that will basically bind another iterator to do the cast on each element. This action will work if Foo : IFoo

, so everything will be fine.

In .NET 2.0, you mostly have to write Cast

yourself, which is easy enough - especially if you don't need to do keyboard shortcuts:

public static IEnumerable<TResult> Cast<TSource, TResult>
    (IEnumerable<TSource> source)
{
    foreach(TSource item in source)
    {
        yield return (TResult) (object) item;
    }
}

      

The double throw is a little awkward, but it works ...

+10


source


Would a general method be acceptable?

interface IFoo { }
class Foo : IFoo { }
static void F<T>(IEnumerable<T> data) where T : IFoo
{ 
    foreach(T item in data) {
       // compiler knows that `item` is an `IFoo` etc
    }
}

...
List<Foo> foos = new List<Foo>();
F(foos);

      



Otherwise; wait for .NET 4.0 / C # 4.0 / VS2010.

+1


source







All Articles