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
source to share
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 ...
source to share
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.
source to share