使用从基类列表到泛型方法的项

时间:2014-05-08 14:36:23

标签: c# generics

很难拿到一个好头衔,但让我说我有这种情况。我有一个基类:

public abstract class FooBase
{

}

我有一个通用的实现:

public class MyFoo<T> : FooBase where T : Bar
{

}

到目前为止一切顺利。抽象基础是这样我可以创建这些通用项的异构集合:

List<FooBase> list = new List<FooBase>()
{
    new MyFoo<Bar1>(),
    new MyFoo<Bar2>()
} 

现在问题来了。我有一个通用的方法:

public void DoSomething<T>(MyFoo<T> aFoo) where T : Bar
{

}

当我使用特定 Foo的实例调用它时,此功能正常工作:

DoSomething(new MyFoo<Bar1>());

但是我想要一个能够获取列表并在每个项目上调用DoSomething的函数:

public void DoSomethingWithList(List<FooBase> list) 
{
    foreach (var item in list) 
    {
        DoSomething(item);     // doesn't work - type cannot be inferred here
    }
}

那么有没有办法在运行时让它找出正确的类型并调用泛型函数?还是有其他方法摆脱这个难题?

2 个答案:

答案 0 :(得分:5)

您可以使用动态类型 - 它将在执行时使用item引用的对象的实际类型执行重载解析。您只需将迭代器类型更改为dynamic,如下所示:

public void DoSomethingWithList(List<FooBase> list) 
{
    foreach (dynamic item in list) 
    {
        DoSomething(item);
    }
}

请注意,如果您的列表中的FooBase最终不是 MyFoo<T>,则会导致执行时间失败。您可以通过提供另一个重载来避免(如果您愿意):

public void DoSomething(FooBase x)
{
    // This will be called for any items in the list that aren't
    // MyFoo<T>
}

这种方法的缺点:

  • 它有一些性能影响;该重要性是否取决于您的应用,但您应该对其进行测试。
  • 您失去了编译时类型安全性。
  • 在C#4之前没有工作,这是dynamic被引入的时候。

如果可以通过重新设计来避免陷入这种情况,那通常是一个好主意......但有时你确实需要这样的东西。

答案 1 :(得分:0)

不,因为必须在编译时知道泛型类型,并且您的示例不向编译器提供信息,他应该使用什么类型,您必须在方法调用中手动插入类型