2009-07-26 89 views
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); 
    } 

回答

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方法可以访问从Type到某个代表的Dictionary映射。

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); 

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

4

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

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

Eric Lippert在此有一个相关博客条目:Double Your Dispatch, Double Your Fun

2

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

0

我觉得在编译器知道第一个重载应该被称为入口点的上下文,因为它是静态绑定不是动态