2011-11-23 123 views
21

以下F#代碼聲明瞭基類和子類。基類有一個默認實現的虛擬方法'測試'。後代類重寫基類方法,並添加一個新的重載「測試」方法。這段代碼編譯得很好,並且在訪問任何後代'Test'方法時不會出現問題。無法解析已被C#覆蓋並重載的F#方法。

F#代碼:

module OverrideTest 
    [<AbstractClass>] 
    type Base() = 
    abstract member Test : int -> int 
    default this.Test x = x + 1 

    type Descendant() = 
    inherit Base() 
    override this.Test x = x - 1 
    member this.Test (x, y) = x - y 

然而,試圖從C#的結果調用 '測試' 的後裔的覆蓋編譯錯誤:

var result = td.Test(3); <- No overload for method 'Test' takes 1 arguments

完整的C#代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace Client 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     var td = new OverrideTest.Descendant(); 
     var result = td.Test(3); 
     Console.WriteLine(result); 
     Console.ReadKey(); 
    } 
    } 
} 

奇怪的是,VisualStudio的intellisense看到了兩個重載函數,並提供兩者的正確簽名。它在構建失敗之前不會給出任何警告或錯誤,只會在之後突出顯示該行。

我已經在C#中完全重新實現了這個場景,並沒有遇到同樣的問題。

任何人有任何想法這裏發生了什麼?

+0

您是否比較了兩種語言中發射的IL? – Oded

+0

如果在調用方法之前將C#代碼上傳到基類會發生什麼? – Brian

+0

@Brian:這很有效。 – Daniel

回答

17

毫無疑問,你知道,如果你省略從​​型Test(x,y)成員 - 或者乾脆將其重命名Test2(x,y) - 那麼C#代碼編譯和運行符合預期。

看着你原來​​類型產生的IL提供了一個線索:

.method public hidebysig virtual 
    instance int32 Test (
     int32 x 
    ) cil managed ... 

.method public 
    instance int32 Test (
     int32 x, 
     int32 y 
    ) cil managed ... 

請注意,有一個在Test(x,y)方法沒有hidebysig屬性。

ECMA CLI specification關於hidebysig有以下說法。 (第15.4.2.2,強調以粗體是我的。)

hidebysig is supplied for the use of tools and is ignored by the VES. It specifies that the declared method hides all methods of the base class types that have a matching method signature; when omitted, the method should hide all methods of the same name, regardless of the signature.

所以,F#編譯器省略了hidebysig屬性,這意味着Test(x,y)方法隱藏命名Test所有其他方法。儘管hidebysig只是「用於工具的使用」,但似乎C#編譯器是使用它的工具之一!

在我看來,它可能是F#編譯器中的一個錯誤,但由於我從來沒有看過F#規範,因此總是有可能允許/指定行爲。

+0

+1:必須閱讀幾次才能掌握'相同名稱'。海事組織的句子的最後部分也應該是** BOLD **。 – leppie

+0

這就是_got_成爲一個bug。對? – Daniel

+0

@Daniel:我想不出爲什麼應該省略hidebysig的原因。 (我從來不知道這個) – leppie