问题描述
被发现在这个问题这个看似不一致的行为可以被复制如下无论是在F#2.0和F#3.0 RC:
Being spotted in context of this question this seeminglyinconsistent 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:
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?
更新:这相关答案通信从F#开发团队的确认,截至目前的错误已经发生的泛型类型参数的处理与 ParamArray参数
属性。
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.
推荐答案
目前,此案略显混乱,因为当你使用一个数组作为一个实际的参数标有 ParamArray参数
,语言尝试跨preT它,如果你是传球达阵,以一个正常的数组类型的参数(因此它忽略了 ParamArray参数
属性,如果可能的话)。
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|]
该编译器将指示'T
是 INT
等你传递 INT []
来类型的参数 INT []
等编译器会忽略 ParamArray参数
属性该方法只是获取包含数组 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|]
该方法需要类型的参数 OBJ [
]和参数的类型是 INT []
,所以这两种类型无法统一(关键是编译器不会自动转换 INT []
到 OBJ []
)。由于这是不可能的,它认为 ParamArray参数
属性,并尝试转换 INT []
到 OBJ
,并将其作为 ParamArray参数
- 这是一个转换编译器可以自动执行,所以你得到你所描述的结果。
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.
如果你叫 Heterogeneous.Echo
与 OBJ []
作为参数,那么它会表现得类似于 Generic.Echo
。例如:
If you called Heterogeneous.Echo
with obj[]
as an argument, then it would behave similarly to Generic.Echo
. For example:
Heterogeneous.Echo [| box 0 |]
如果你想进入的细节,你可以看看节14.4。的 F#语言规范。但是,重载决策规则是pretty的复杂,所以我没有一个确切的参考,解释这种行为 - 只是一个非正式的解释,上述
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.
这篇关于在F#泛型参数的ParamArray不一致的处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!