5

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

4

5 回答 5

10

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

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

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

如果您不使用 .NET 4,那就更难了——您可以使用反射,或者对选项进行硬编码,这两种方法都不好玩。

于 2013-01-25T14:07:22.123 回答
5

您可以使用以下dynamic类型:

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

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

于 2013-01-25T14:06:40.110 回答
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
    }

当您使用简单的覆盖概念时,它将运行运行时类型方法。

于 2013-01-25T14:08:52.683 回答
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());
}
于 2013-01-25T14:13:33.070 回答
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
于 2013-01-25T14:14:09.523 回答