2011-10-20 4 views
0

次のコードがコンパイルされないのはなぜですか?これはコンパイラのバグか言語機能ですか?最善の回避策は何ですか?ジェネリックの問題

type A() as this = 
    let a = this.GetTypedObject<int>() // a 
    let b = this.GetTypedObject<string>() // b 

    member this.GetTypedObject<'T>() = 
     Unchecked.defaultof<'T> 

Unchecked.defaultof <「T>は単に例のために使用される、任意の関数またはコンストラクタコールを代わりに使用することができます。

コンパイラでは、コードは線分(a)で一般的でなくなり、線分(b)をコンパイルすることを拒否します。 私はロシア語で書いてあるので、コンパイラの正確なメッセージを伝えることはできません:)。

GetTypedObject()をレットバインディングに変換して削除すると、< 'T>は別のコンパイラの警告で終わってしまいます。私が見つけた唯一のwokaroundは、GetTypedObject < 'T>()を基本クラスに移動して公開することです。事前のおかげで...

答えて

3

型推論は、上から下に動作しているため、 それがさえメソッドの定義に達し、それが 汎用的でなければなりません発見する前にGetTypedObjectintを返す遭遇します。 (ブライアンが指摘するように、メンバーが前letバインディングに読み出され...そして、このためのシンプルな修正プログラムがあります。)私は、次の厄介なエラーが発生します。

A use of the function 'GetTypedObject' does not match a type inferred elsewhere. The inferred type of the function is Test.A -> Microsoft.FSharp.Core.unit -> 'a. The type of the function required at this point of use is Test.A -> Microsoft.FSharp.Core.unit -> 'a This error may be due to limitations associated with generic recursion within a 'let rec' collection or within a group of classes. Consider giving a full type signature for the targets of recursive calls including type annotations for both argument and return types.

使用量は、メソッド定義の後に表示された場合は、できます。ここで

type A() = 
    member this.GetTypedObject<'T>() = 
     Unchecked.defaultof<'T> 

    member this.Test() = 
     let a = this.GetTypedObject<int>() // a 
     let b = this.GetTypedObject<string>() // b 
    () 

は、回避策です:あなたは、単にこの問題を解決するために型注釈を追加できること

type A() = 
    let getTypedObject() = Unchecked.defaultof<_> 
    let a : int = getTypedObject() // a 
    let b : string = getTypedObject() // b 

    member this.GetTypedObject<'T>() : 'T = getTypedObject() 
+0

ありがとうございます!私の魅力のように働いた。 – Alexander

+0

そして優れた説明! – Alexander

4

注:

type A() as this = 
    let a = this.GetTypedObject<int>() // a 
    let b = this.GetTypedObject<string>() // b 

    member this.GetTypedObject<'T>() : 'T = 
            //^^^^ 
     Unchecked.defaultof<'T> 

メンバーの署名が最初に読み込まれます、そして、すべてのletとメンバーそれは型推論の秩序に当てはまる。戻り値の型を宣言シグニチャーに入れることで、それがトークンに表示されます。

+0

ありがとうございます。その解決策が簡単にできると想像できませんでした:) – Alexander

関連する問題