在这个问题的上下文中,这种看似不一致的行为可以在F#2.0和F#3.0 RC中复制如下:
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属性的泛型类型参数时,有一个bug。
发布于 2012-06-17 20:08:50
这种情况有点混乱,因为当您使用数组作为标记为ParamArray的参数的实际参数时,语言试图将其解释为将数组传递给正常的数组类型参数(因此,如果可能,它将忽略ParamArray属性)。
在您的示例中,这在第二种情况下是可能的:
Generic.Echo [|0|]编译器推断'T是int,所以您将int[]传递给int[]类型的参数,因此编译器忽略ParamArray属性,该方法只获得一个包含0的数组。
在另一种情况下,这是不可能的:
Heterogeneous.Echo [|0|]该方法需要一个obj[]类型的参数,而参数的类型是int[],因此不能统一这两种类型(关键是编译器不会自动将int[]转换为obj[])。由于这是不可能的,所以它会考虑ParamArray属性,并尝试将int[]转换为obj并将其作为ParamArray的成员传递--这是编译器可以自动执行的转换,因此您将得到所描述的结果。
如果您使用Heterogeneous.Echo作为参数调用obj[],那么它的行为将类似于Generic.Echo。例如:
Heterogeneous.Echo [| box 0 |]如果你想详细谈谈,你可以看第14.4节。F#语言规范的。然而,过载解决规则相当复杂,因此我没有确切的参考来解释这种行为--只是上面的一个非正式解释。
https://stackoverflow.com/questions/11074227
复制相似问题