繁体   English   中英

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

[英]Calling method based on run-time type insead of compile-time type

在应用程序中,我需要.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#编译器”将在执行时应用与编译时相同的规则,但使用这些dynamic的实际执行时类型价值观。 (尽管其类型在编译时是静态已知的表达式仍然会被视为具有这些类型-并不能使有关重载解析的所有内容变为动态。)

如果您不使用.NET 4,则难度会有所增加-您可以使用反射,也可以对选项进行硬编码,但都不有趣。

您可以使用dynamic类型:

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

但是,请注意,这样做的缺点是,如果没有匹配的方法,它将生成运行时异常,而不是编译错误。

使用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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM