当编译时类型未知时,如何选择方法重载

本文关键字:选择 方法 重载 类型 编译 未知 何选择 | 更新日期: 2023-09-27 17:57:51

假设我有以下代码:

public class SomeClass
{
    // Other stuff...
    public void ApplyEvent<T>(IPublishedEvent<T> evt)
    {
        Handle(evt.Payload);
    }
    protected virtual void Handle(ThingyCreatedEvent evt)
    {
        Code = evt.Code;
        Label = evt.Label;
    }
    protected virtual void Handle<T>(T evt)
    {
        throw new NotImplementedException(
            String.Format("Not set to handle {0}", evt.GetType().FullName));
    }
}

evt。Payload的类型是T。我希望能够处理我期望的特定事件类型的方法,并有一个catch-all方法,如果出于某种原因提供了意外的事件类型,该方法将抛出。

不过,我发现,即使T是ThingyCreatedEvent类型,也会调用泛型方法,除非我显式强制转换它:

Handle(evt.Payload as ThingyCreatedEvent);

如果我定义了一个带有Object类型参数的Handle方法,而不是通用的Handle法,我会得到同样的结果。

有人能解释一下吗?我想更好地了解这里发生了什么。我本以为它会根据运行时提供的实际类型进行调度。

当编译时类型未知时,如何选择方法重载

泛型在编译时解析-编译器需要知道T的类型是什么。如果你想使用将在运行时解析的类型,你应该查找关键字"dynamic"。

所有代码(包括重载解析)在正常编译时都会编译一次,除非有约束,否则必须在不知道T是什么的情况下做出重载决策。调用Handle(evt.Payload);的方法只在知道evt.Payload的类型是T的情况下解析一次,因此它必须解析为Handle<T>(T evt)

如果你真的想在执行时解决过载问题,如果你使用的是C#4,你可以使用动态键入:

public void ApplyEvent<T>(IPublishedEvent<T> evt)
{
    dynamic payload = evt.Payload;
    Handle(payload);
}