Inconsistent processing of generic ParamArray argument in F#

生来就可爱ヽ(ⅴ<●) 提交于 2020-01-02 06:41:46

问题


Being spotted in context of this question this seemingly inconsistent behavior can be reproduced as following both in F#2.0 and F#3.0 RC:

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

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

Usage:                                                              Returns:

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

Can anyone explain if the observed behavior is a bug, or feature?

UPDATE: This related answer communicates a confirmation from F# development team that as of now a bug has place in processing of generic type arguments with ParamArray attribute.


回答1:


The case is slightly confusing because when you use an array as an actual argument to a parameter marked with ParamArray, the language tries to interpret it as if you were passing array to a normal array-typed parameter (so it ignores the ParamArray attribute if possible).

In your example, this is possible in the second case:

Generic.Echo [|0|]

The compiler infers that 'T is int and so you're passing int[] to a parameter of type int[] and so the compiler ignores ParamArray attribute and the method simply gets an array containing 0.

In the other case, this is not possible:

Heterogeneous.Echo [|0|]

The method expects a parameter of type obj[] and the type of the argument is int[], so the two types cannot be unified (the key is that the compiler does not automatically convert int[] to obj[]). Since this is not possible, it considers the ParamArray attribute and tries to convert int[] to obj and pass it as a member of ParamArray - this is a conversion that the compiler can automatically perform and so you get the result you described.

If you called Heterogeneous.Echo with obj[] as an argument, then it would behave similarly to Generic.Echo. For example:

Heterogeneous.Echo [| box 0 |]

If you want to go into details, you can look at section 14.4. of the F# language specification. However, the overload resolution rules are pretty complex and so I don't have an exact reference that explains this behaviour - just an informal explanation above.



来源:https://stackoverflow.com/questions/11074227/inconsistent-processing-of-generic-paramarray-argument-in-f

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!