2012-10-11 55 views
4

靈感來自this question我曾嘗試在Mono 2.10.9一個下面的代碼和Visual Studio 2010:如何在存在非靜態,更合適的方法時使用動態參數調用靜態方法?

public class Example 
{ 
    public static void Main() 
    { 
     Foo(1); 
    } 

    public static void Foo(dynamic x) 
    { 
     Example.Bar(x); 
    } 

    static void Bar(dynamic x) 
    { 
     x++; 
    } 

    int count; 
    void Bar(int x) 
    { 
     count++; 
    } 
} 

正如你所看到的,Foo是靜態的,所以它只能訪問靜態Bar - 我明確地調用靜態版本!

我知道我將無法聲明static void Bar(int x),因爲存在非靜態版本。

但是,將非靜態的參數類型Bar更改爲,比方說,字符串,使一切正常。

這是爲什麼?這裏有什麼規則?有沒有可能調用靜態方法?

也許這是單反DLR的問題?

編輯:澄清。我想知道什麼規則將一個明確的調用靜態方法(至少我認爲這是明確的)變成一個調用一個非靜態的一個?這顯然不可能從靜態的上下文中。

或者,如果沒有這樣的規則,它可以是錯誤?這種行爲可以以某種方式避免嗎?

+1

請注意:AFAIK,Mono擁有來自MS的Apache授權DLR實施。 –

+0

你問你爲什麼可以在擺脫static void Bar(int x)後添加'void bar(int x)' –

+0

你在這裏問什麼? –

回答

1

的關鍵語句有「我知道我將無法聲明靜態無效欄(int x),因爲存在非靜態版本。」使用dynamic關鍵字會將重載解析推遲到運行時,但在運行時出現時,它不會免除該規則。

當重載分辨率最終出現時,DLR將評估所有可用選項,然後選擇最佳選項。在這個解析時間之前,動態類型的參數很像是類型對象(參見here)。因此,通常採用int的更具體的方法將成爲通用分辨率的勝利者,因此被選擇爲採用動態/對象的方法。這意味着實例方法通常會獲勝。 DLR知道具有相同簽名的兩種方法不能因靜態而變化。當評估可用的選項時,你期望它做的是「aha!在這種情況下,靜態無效欄(動態x)可以被解釋爲靜態無效欄(int x)」。但是,如果確實如此說明,那麼關於不具有其他方面相同的靜態和非靜態方法的規則將被違反。它的內部選項列表將包含靜態和非靜態Bar方法,它們都具有相同的簽名。所以它不能這麼說。這留下了唯一的其他選項,這恰好是一種實例方法。在這種情況下這是沒有用的,所以DLR引發RuntimeBinderException。如果將實例Bar的參數更改爲除int之外的其他值,那麼方法簽名不會發生衝突,因此DLR可以將靜態動態Bar解釋爲接受一個int值,然後選擇該超載值。

+0

好吧,這很有道理:)我很想知道是否有可能在DLR引擎中實現這樣的場景,但我不認爲有人會告訴我;]感謝您的一個很好的澄清! –

0
static void Bar(dynamic x) 
    { 
     x++; 
    } 

    int count; 
    void Bar(int x) 
    { 
     count++; 
    } 

靜態函數可以看作是(可以這麼用整型參數的靜態方法的調用將調用非靜態,更好的擬合方法):

static void Bar(dynamic x) 
    { 
     if (x is Int) 
      Bar(x); //Count++ 

     else 
      x++; 
    } 
+0

但我們在這裏混合靜態和非靜態上下文。我認爲一個叫'Example.Bar(x)'直接指向我們的靜態方法... –

相關問題