2011-11-23 21 views
21

次のF#コードは、ベースクラスと子孫クラスを宣言しています。基本クラスには、デフォルトの実装を持つ仮想メソッド 'Test'があります。子孫クラスは基本クラスのメソッドをオーバーライドし、新しいオーバーロードされた 'Test'メソッドも追加します。このコードはうまくコンパイルされ、子孫の 'Test'メソッドのいずれかにアクセスする際に問題はありません。C#からオーバーライドされオーバーロードされたF#メソッドを解決できません

F#コード:

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(); 
    } 
    } 
} 
コンパイルエラーにC#の結果から 'テスト' の子孫のオーバーライドを起動しようとするしかし

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 

奇妙なことは、VisualStudioのインテリセンスが2つのオーバーロードされた関数を見て、両方の正しい署名。ビルドに失敗する前に警告やエラーを表示せず、後でその行だけをハイライト表示します。

私はこのシナリオをC#で完全に再実装しており、同じ問題にぶつからなかった。

誰もがここで何が起こっているか考えていますか?

+0

放出されたILを両方の言語で比較しましたか? – Oded

+0

C#コードでメソッドを呼び出す前にベースクラスにアップキャストした場合はどうなりますか? – Brian

+0

@ブライアン:それは動作します。 – Daniel

答えて

17

あなたが​​タイプからTest(x,y)メンバーを省略することを認識して間違いありませんが - あるいは単にはTest2(x,y)に名前を変更 - 予想通りその後、C#コードをコンパイルして実行します。 Test(x,y)方法はhidebysig属性がないことを

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

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

注意:元​​タイプ用に生成されたILを見てみると

は手掛かりを提供しています。

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#コンパイラはTest(x,y)方法がTestという名前の他のすべてのメソッドを隠していることを意味し、hidebysig属性を省略します。 hidebysigは「ツールの使用のためだけ」ですが、C#コンパイラはそれを使用するツールの1つです!

これはF#コンパイラのバグかもしれませんが、私はF#仕様を見たことがないので、これは常に許可されている/指定された動作である可能性があります。

+0

+1:「同名」を把握するために数回読む必要がありました。 IMO文の最後の部分は** BOLD **でなければなりません。 – leppie

+0

これはバグではない_ _です。右? – Daniel

+0

@Daniel:私はなぜ「hidebysig」を省略すべきなのか考えることはできません。 (私はこれについて一度も知らなかった) – leppie

関連する問題