方法重载

时间:2009-07-26 06:59:04

标签: c# overloading

当我使用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 个答案:

答案 0 :(得分:4)

  

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

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

Eric Lippert有一篇相关的博客文章:Double Your Dispatch, Double Your Fun

答案 1 :(得分:2)

当您使用EntryPoint()类型的参数调用TemplateA时,会将其转换为object。因此,对myFunc(p)的后续静态绑定调用将使用object类型的参数进行。

答案 2 :(得分:1)

如果您使用dynamic而不是object,则可以在C#4.0中执行此操作。如果您想尝试一下,请下载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);

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

答案 3 :(得分:0)

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