我正在尝试将一个作为对象传递的参数(它是一个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);
由于
朱塞佩
答案 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>();
}
基本上,这会使用弱类型的IEnumerable
(IEnumerable<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。