2009-07-26 123 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

我覺得在編譯器知道第一個重載應該被稱爲入口點的上下文,因爲它是靜態綁定不是動態