4

当我遇到这种情况并意识到我不确定最好的解决方案是什么时,我感到很惊讶。

假设我有以下三种类型:

class A { }
class B : A { }
class C : A { }

以及以下三种方法:

DoSomething(A a){ }
DoSomething(B b){ }
DoSomething(C c){ }

我有一个List<A>包含 B 和 C 类型的对象

我想这样做:

foreach(A a in list) { DoSomething(a) }

并让它调用与底层类型最匹配的方法,但当然这总是会调用DoSomething(A a)

我不希望有一堆类型检查来获得正确的方法调用,并且我不想向 A、B 或 C 类添加任何内容。

是否可以?

4

3 回答 3

7

这是静态类型语言中虚拟调度的一个众所周知的问题:它只“虚拟”处理一个参数( );this对于所有其他参数,方法调用使用参数的静态类型进行绑定。由于您的列表是 的列表A,因此代码只会调用A重载。

您需要多次分派才能实现既定目标,并且由于除非您切换到 ,否则该语言不会开箱即用地提供此功能dynamic,因此您必须自己进行切换或实现它。在做出此决定时(以及在决定如何在需要时实现多分派时)需要考虑许多权衡,所以不要轻易这样做。

于 2012-11-26T20:10:26.033 回答
3

您将付出性能成本,但实现此目的的一种简单方法是使用动态运行时绑定器。只需将参数转换为dynamic

foreach(A a in list) { DoSomething((dynamic)a); }
于 2012-11-26T20:11:13.050 回答
3

如果您愿意使用dynamic关键字,我想像

DoSomething((dynamic)a);

将为您完成工作。

否则,对于静态类型,您可以说

void DoSomething(A a)
{
  var aAsB = a as B;
  if (aAsB != null)
    DoSomething(aAsB);
  var aAsC = a as C;
  if (aAsC != null)
    DoSomething(aAsC);

  // general A case here
}

但这也许就是你所说的一堆类型检查。

于 2012-11-26T20:11:36.890 回答