3

当我使用 TemplateA 类型的参数调用 EntryPoint 时,总是会收到异常,因为总是调用第一个重载。
我期望发生的是,由于动态绑定,将调用最具体的方法(第二次重载)。
任何想法为什么?

private object _obj;
    public void EntryPoint(object p)
    {
        myFunc(p);
    }

    //first overload
    private void myFunc(object container)
    {
        throw new NotImplementedException();
    }

    //second overload
    private void myFunc(TemplateA template)
    {
        _obj = new ObjTypeA(template);
    }

    //third overload
    private void myFunc(TemplateB template)
    {
        _obj = new ObjTypeB(template);
    }
4

4 回答 4

4

我期望发生的是,由于动态绑定,将调用最具体的方法(第二次重载)。

您在哪里看到动态绑定?变量的静态类型是object. 除非您直接在其上调用虚拟方法,否则不会发生动态调度。重载在编译时完全静态解决。

Eric Lippert 有一篇相关的博客文章:双倍调度,双倍乐趣

于 2009-07-26T07:02:38.087 回答
2

当您EntryPoint()使用类型参数调用时TemplateA,它被强制转换为object. 因此,随后的静态绑定调用myFunc(p)使用 type 的参数进行object

于 2009-07-26T07:04:22.263 回答
1

如果您使用dynamic而不是object. 如果您想尝试一下,请下载 Visual Studio 2010 Beta。在此之前,编译器会根据参数的编译时类型准确选择要调用的方法。

从您的问题中不清楚您是否了解普通的单调度多态性,因为它可以解决您的示例问题。

class TemplateBase
{
    public virtual object MyFunc()
    {
        throw new NotImplementedException();
    }
}

class TemplateA : TemplateBase
{
    public override object MyFunc()
    {
        return new ObjTypeA(this);
    }
}

class TemplateB : TemplateBase
{
    public override object MyFunc()
    {
        return new ObjTypeB(this);
    }
}

在其他地方:

private object _obj;

public void EntryPoint(TemplateBase p)
{
    _obj = p.MyFunc();
}

当您无法修改TemplateN类时,还有其他选择。最简单的方法是让该EntryPoint方法可以访问某个委托的Dictionary映射。Type

Dictionary<Type, Func<object, object>> _myFuncs;

_myFuncs.Add(typeof(TemplateA), o => new ObjTypeA((TemplateA)o));
_myFuncs.Add(typeof(TemplateB), o => new ObjTypeB((TemplateA)o));

然后它可以查找要为传递给它的对象类型执行的委托。

Func<object, object> f = _myFuncs[p.GetType()];
_obj = f(p);

但是,如果您想模仿虚函数的确切工作方式,则需要注意继承层次结构。

于 2009-07-26T08:36:37.770 回答
0

我认为在 EntryPoint 上下文中,编译器知道应该调用第一个重载,因为它是静态绑定而不是动态的

于 2009-07-26T07:05:41.590 回答