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

本文关键字:泛型方法 基类 列表 | 更新日期: 2023-09-27 18:02:28

很难想出一个好的标题,但假设我有这种情况。我有一个基类:

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

那么有没有一种方法,在运行时让它找出正确的类型并调用泛型函数?或者还有其他方法可以解决这个难题吗?

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

您可以使用动态类型-它将在执行时对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被引入的时候。
如果你可以通过重新设计来避免陷入这种情况,这通常是个好主意…但有时你确实需要这样的东西

不,由于泛型类型必须在编译时已知,并且您的示例没有向编译器提供应该使用哪种类型的信息,因此您必须在方法调用

中手动插入类型。