4

この質問の文脈で発見されると、この一見一貫性のない動作は、F#2.0とF#3.0RCの両方で次のように再現できます。

type Heterogeneous =
    static member Echo([<ParamArray>] args: Object[]) = args

type Generic =  
    static member Echo<'T>([<ParamArray>] args: 'T[]) = args

使用法:戻り値:

Heterogeneous.Echo 0              // [|0|]                OK
Generic.Echo 0                    // [|0|]                OK
Heterogeneous.Echo (0,1)          // [|0; 1|]             OK
Generic.Echo (0,1)                // [|0; 1|]             OK
Heterogeneous.Echo [|0|]          // [|[|0|]|]            OK?
Generic.Echo [|0|]                // [|0|]                OOPS!!
Heterogeneous.Echo ([|0|],[|1|])) // [|[|0|]; [|1|]|]     OK
Generic.Echo ([|0|],[|1|]))       // [|[|0|]; [|1|]|]     OK

観察された動作がバグなのか機能なのかを誰かが説明できますか?

更新: この関連する回答は、F#開発チームからの確認を伝えており、現在、ParamArray属性を持つ汎用型引数の処理にバグがあります。

4

1 に答える 1

5

ParamArrayでマークされたパラメータの実際の引数として配列を使用すると、言語は配列を通常の配列型パラメータに渡しているかのように解釈しようとするため、このケースは少し混乱します(したがってParamArray、可能であれば属性を無視します)。

あなたの例では、これは2番目のケースで可能です。

Generic.Echo [|0|]

コンパイラはそれを推測するので、型のパラメータを渡して'Tいるので、コンパイラは属性を無視し、メソッドは単に。を含む配列を取得します。intint[]int[]ParamArray0

その他の場合、これは不可能です。

Heterogeneous.Echo [|0|]

このメソッドは型のパラメーターを想定してobj[]おり、引数の型はint[]であるため、2つの型を統合することはできません(重要なのは、コンパイラーが自動的にに変換しないint[]ことobj[]です)。これは不可能であるため、ParamArray属性を考慮し、変換int[]objてメンバーとして渡そうとしますParamArray。これは、コンパイラーが自動的に実行できる変換であり、説明した結果が得られます。

Heterogeneous.Echo引数としてwithを呼び出すと、。obj[]と同様に動作しGeneric.Echoます。例えば:

Heterogeneous.Echo [| box 0 |]

詳細を知りたい場合は、セクション14.4をご覧ください。F#言語仕様の。ただし、過負荷解決ルールは非常に複雑であるため、この動作を説明する正確なリファレンスはありません。上記の非公式な説明にすぎません。

于 2012-06-17T20:08:50.463 に答える