【问题标题】:Call child class method using dynamic keyword使用动态关键字调用子类方法
【发布时间】:2023-03-21 13:07:02
【问题描述】:

我有几个类都实现了接口IBar。这些类是BarABarBBarC

我还有一个基类Foo

abstract class Foo
{
    void Do(IBar bar)
    {
        Handle((dynamic)bar);
    }

    void Handle(IBar bar)
    {
        Console.Out.WriteLine("Fallback Scenario");
    }
}

我想要一个子类FooChild,如下所示:

class FooChild : Foo
{
    void Handle(BarA bar) {
        Console.Out.WriteLine("Handling BarA");
    }

    void Handle(BarB bar) {
        Console.Out.WriteLine("Handling Bar");
    }
}

不,我想执行以下操作,但没有得到预期的结果

var foo = new FooChild();
foo.Handle(new BarA()); // expected: Handling BarA, actual: Fallback Scenario
foo.Handle(new BarB()); // expected: Handling BarB, actual: Fallback Scenario
foo.Handle(new BarC()); // expected: Fallback Scenario, actual: Fallback Scenario

我可以通过将Do(IBar bar) 方法移动到FooChild 类来解决它,但我不想这样做。我可能有 10 个Foo 孩子并且不想重复该代码。有解决办法吗?

【问题讨论】:

    标签: c#-4.0 inheritance dynamic


    【解决方案1】:

    我想你想要这个:

    void Do(IBar bar)
    {
        dynamic dynamicThis = this;
        dynamicThis.Handle((dynamic) bar);
    }
    

    这样,将根据this实际 类型找到该方法。否则,编译器会记住该方法是从Foo 调用的,并且只动态处理参数,查找可以从Foo 获得的方法,实际类型为bar。您想要的方法可以从this 的实际类型以及使用bar 的实际类型(通过转换为dynamic)获得。

    (不过,您需要公开 Handle 方法。)

    【讨论】:

    • 您好乔恩,感谢您的回答!它几乎起作用了;我必须在方法调用中保留(动态)强制转换以使其成功运行。
    • @avanwieringen:啊,是的——否则它仍然会尝试使用编译时类型。我会为未来的访客修正我的答案。
    • 所以如果我是正确的,动态关键字将根据运行时知识而不是编译时知识进行匹配?
    • @avanwieringen:这是动态表达式的行为,是的。但是编译器保留它确实作为这些表达式的一部分的任何编译时知识 - 所以如果你有Method(x, y),其中x的编译时类型是dynamic,但编译时- y 的时间类型只是object,它只会匹配第二个参数是object 的方法,而不管y 的执行时间类型。
    • 值得注意的是:当我的 FooChild 是一个嵌套的私有类(对于单元测试)时,这不起作用。将其公开工作。很好奇为什么 RuntimeBinder 无法正确解析它,即使它通过调试器看起来很好。
    猜你喜欢
    • 2012-12-05
    • 2015-09-26
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多