动态调度到 C# 中的派生类

本文关键字:派生 动态调度 | 更新日期: 2023-09-27 18:34:43

我正在尝试执行以下操作:

public abstract BaseClass {
  public virtual void ReceiveEvent(Event evt)
    {
        ProcessEvent(evt as dynamic);
    }
    private void ProcessEvent(object evt)
    { 
        LogManager.Log(@"Received an event that is not being processed! 
                        Dispatch fallback");
    }
}
public DerivedClass: BaseClass {
    private void ProcessEvent(SpecificEvent evt)
    { 
        LogManager.Log("Processing Event");
    }
}

特定事件命中回退方法,而不是派生类中的回退方法。我一直在同一类中使用动态调度,并发现它非常有用/干净。它不适用于上面示例中所示的派生类吗?

编辑:答案似乎有些混乱。基本上我一直使用以下设计:

public class SomeClass{
    public void DoSomethingDispatcher(SomeObject obj)
    {
        ProcessObject(obj as dynamic);
    }
    private void DoSomething(SomeObjectType1 obj)
    { 
    }
    private void DoSomething(SomeObjectType2 obj)
    { 
    }
    private void DoSomething(SomeObjectType3 obj)
    { 
    }
    private void DoSomething(object obj) //fallback
    { 
    }
}
当您

事先不知道确切的类型并且不想使用大的 switch 语句时,它非常有用。只是想知道这是否可以通过继承来实现,其中基类保存回退方法,派生类保存所有更具体的方法。

动态调度到 C# 中的派生类

它不适合您,因为即使 evt 是动态传递的,ProcessEvent 也不会声明为虚拟的。这意味着,当编译对 ProcessEvent 的调用时,它将链接到在基类中找到的方法的唯一实现,并且永远不会执行派生类中的方法。此外,您不能简单地将 ProcessEvent 声明为虚拟,因为派生类中的签名会有所不同。

为了使您的代码按预期工作,您只需在派生类中重写 ReceiveEvent,使其完全相同:

  public override void ReceiveEvent(Event evt)
    {
        ProcessEvent(evt as dynamic);
    }

如果要管理基类中未处理的事件,只需将基类中的 Process 事件的修饰符更改为受保护(否则在被重写的 ReceiveEvents 版本调用时无法执行(。

如果该方法在基类中未virtual/abstract,并且该方法未在派生类中标记为override,则它将永远不起作用。

另外,我不明白这里dynamic的用法。

你的"evt"在点击ProcessEvent时是什么类型?

你可以看看 使用类型 动态 :

类型是静态类型,但动态类型的对象会绕过 静态类型检查。在大多数情况下,它的功能就像它有类型 对象。

所以,evt 不是SpecificEvent.

要获得预期的行为,您应该覆盖虚拟方法:

public DerivedClass: BaseClass
{
  private override void ReceiveEvent(Event evt)
  { 
      // Process your event here.
  }
}

使用此代码,不会调用基类中的ReceiveEvent,因此不会调用回退ProcessEvent

没有理由使用dynamic.