基于编译时类型的运行时类型的调用方法

在应用程序中,我需要.NET基于其运行时类型而不是其编译时类型来调用方法。

简化示例:

class A { } class B : A { } static void Main(string[] args) { A b = new B(); Print(b); } static void Print(A a) { Console.WriteLine("Called from A"); } static void Print(B b) { Console.WriteLine("Called from B"); } 

上面的代码实际上是打印Called from A ,但我需要它Called from B

这按预期工作:

 static void Print(A a) { var b = a as B; if (b != null) return Print(b); else Console.WriteLine("Called from A"); } 

但出于可维护性的考虑,这是不可取的。

我相信这个问题与此类似: 为什么不根据对象的运行时类型选择此方法? ,但对于.NET而不是Java。

如果您使用的是.NET 4或更高版本,最简单的方法是使用动态类型 :

 dynamic b = new B(); Print(b); 

几乎所有使用dynamic类型的表达式都将动态调用,“mini-C#编译器”在执行时应用与编译时相同的规则,但使用那些动态的实际执行时类型值。 (类型在编译时静态已知的表达式仍将被视为具有这些类型 – 它不会使重载决策的所有内容变为动态。)

如果你不使用.NET 4,那就更难了 – 你可以使用reflection,也可以硬编码选项,这两种选择都不好玩。

您可以使用dynamic类型:

 A b = new B(); dynamic tmp = b; Print(tmp); // Prints "Called from B" 

但是,请注意,如果没有匹配方法,它会产生运行时exception而不是编译错误。

使用覆盖OOP。

〔实施例:

 class A { public virtual void Print() { Console.WriteLine("Called from A"); } } class B : A { public override void Print() { Console.WriteLine("Called from B"); } } 

并使用它像:

  A b = new B(); Print(b); static void Print(A a) { a.Print(); //will run B's method } 

它将运行运行类型方法,因为您使用简单的重写概念。

这不是多态性的工作原理。 你应该考虑做一些类似于以下的事情:

 class A { virtual string GetString() { return "Called from A"; } } class B : A { override string GetString() { return "Called from B"; } } static void Main(string[] args) { A b = new B(); Print(b); } static void Print(A a) { Console.WriteLine(a.GetString()); } 

试试这个:

 class A { public virtual string Print() { return "Called from A"; } } class B : A { public override string Print() { return "Called from B"; } } 

并在别处测试

 A b = new B(); MessageBox.Show(b.Print()); //called from B