如果将IEnumerable <foo>类型的对象转换为IEnumerable <ifoo>,如果作为对象传递给函数,该如何?</ifoo> </foo>

时间:2009-10-07 11:10:41

标签: c# generics casting

我正在尝试将一个作为对象传递的参数(它是一个IEnumerable类型的对象的upcast)转发到IEnumerable,其中Foo实现了IFoo。

以下是我想要做的一个例子,但它不起作用。

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

有解决方法吗?我不想让函数F Foo具体,但我无法将其转换为界面,除非我这样做:

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

由于

朱塞佩

2 个答案:

答案 0 :(得分:10)

在.NET 4.0之前,在.NET 4.0之前,你不能 - IEnumerable<T>不变的

使用.NET 4.0,您发布的代码将正常运行。

在.NET 3.5中,您可以使用Enumerable.Cast

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

基本上,这会使用弱类型的IEnumerableIEnumerable<Foo>IEnumerable<IFoo>都会扩展,因此转换会很好)然后应用Cast<T>方法,基本上链接另一个迭代器来对每个项目执行强制转换。如果Foo : IFoo,该演员阵容肯定会奏效,所以你会没事的。

在.NET 2.0中,您必须自己编写Cast,这很容易 - 特别是如果您不需要执行任何快捷方式:

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

双重演员有点尴尬,但它有效......

答案 1 :(得分:1)

通用方法是否可以接受?

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

否则;等到.NET 4.0 / C#4.0 / VS2010。