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

时间:2013-01-25 14:05:39

标签: c# .net polymorphism

在应用程序中,我需要.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。

5 个答案:

答案 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