2012-06-17 54 views
4

通用的ParamArray參數的不一致處理中的this question這種看似 行爲不一致的上下文中發現可被再現爲既在F#2.0和F#3.0 RC以下:在F#

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 

誰能解釋,如果觀察到的行爲是錯誤或功能?

UPDATE:related answer通信從F#開發團隊的確認,截至目前的錯誤已經在泛型類型參數的處理與地方屬性ParamArray

回答

5

這種情況有點令人困惑,因爲當你使用一個數組作爲ParamArray標記的參數的實際參數時,語言試圖解釋它,就好像你正在將數組傳遞給一個正常的數組類型參數一樣(所以它忽略瞭如果可能,則爲ParamArray屬性)。

在你的榜樣,這是可能的第二種情況:

Generic.Echo [|0|] 

編譯器推斷'Tint等你傳遞int[]int[]類型的參數,所以編譯器會忽略ParamArray屬性該方法只需獲取包含0的數組。

在其他情況下,這是不可能的:

Heterogeneous.Echo [|0|] 

的方法,預計obj[]類型的參數和參數的類型是int[],所以這兩種類型無法統一(關鍵是編譯器不會自動將int[]轉換爲obj[])。由於這是不可能的,因此它會考慮ParamArray屬性並嘗試將int[]轉換爲obj並將其作爲ParamArray的成員傳遞 - 這是編譯器可以自動執行的轉換,因此您可以獲得所描述的結果。

如果您以obj[]作爲參數調用Heterogeneous.Echo,則它的行爲與Generic.Echo類似。例如:

Heterogeneous.Echo [| box 0 |] 

如果您想了解詳細信息,請參見第14.4節。的F# language specification。但是,重載解析規則相當複雜,所以我沒有一個確切的參考來解釋這種行爲 - 只是上面的一個非正式解釋。

+0

謝謝,托馬斯!這有助於理解爲什麼[there](http://stackoverflow.com/a/11068951/917053) 明確可用'Observable.StartWith()'重載解決了這個問題。 –