在应用程序中,我需要.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");
}
但出于可维护性的考虑,这是不可取的。
我相信这个问题类似于这个问题:Why isn't this method chosen based on the runtime-type of its object?,但对于.NET而不是Java。
答案 0 :(得分:10)
如果您使用的是.NET 4或更高版本,最简单的方法是使用dynamic typing:
dynamic b = new B();
Print(b);
使用类型dynamic
的值的几乎所有表达式都将被动态调用,“mini-C#编译器”在执行时应用与编译时相同的规则,但使用< em>这些动态值的实际执行时间类型。 (在编译时静态已知类型的表达式仍将被视为具有这些类型 - 它不会使关于重载的所有成为动态的。)
如果你没有使用.NET 4,那就更难了 - 你可以使用反射,也可以硬编码选项,这两种选择都不是很有趣。
答案 1 :(得分:5)
您可以使用dynamic
类型:
A b = new B();
dynamic tmp = b;
Print(tmp); // Prints "Called from B"
但是,请注意,如果没有匹配的方法,它会产生运行时异常而不是编译错误。
答案 2 :(得分:4)
使用覆盖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
}
它将运行 runtime 类型方法,因为您使用简单的重写概念。
答案 3 :(得分:0)
这不是多态性的工作原理。你应该考虑做一些类似于以下的事情:
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());
}
答案 4 :(得分:0)
试试这个:
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