如何调用Bitconverter.Getbytes泛型?

时间:2015-12-19 10:55:19

标签: generics f# inline type-inference

let inline set (x: ^t) = BitConverter.ToUInt32(BitConverter.GetBytes(x),0)

我尝试了类似上面的内容,但它不起作用。类型约束或运行时解析类型都没有。另外,我猜测答案是否定的,但是可以告诉编译器泛型类型只是float32还是float?这会给我带来很多麻烦。

编辑:

令我感到惊讶的是,Tomas Petricek写的是有效的,反过来却没有:

let inline toUint32 conv x = 
  let bytes = conv x
  BitConverter.ToUInt32(bytes, 0)

toUint32 BitConverter.GetBytes 9999.99f 
toUint32 BitConverter.GetBytes 9999.99 

这很有趣。如果没有其他帖子中的conv : BitConvertible,我也无法使其发挥作用。

2 个答案:

答案 0 :(得分:3)

静态成员约束不直接允许您编写将调用重载方法的内联函数。编译器无法决定是否对函数进行类型检查,就好像参数是floatfloat32或任何其他支持的类型一样。

简单的解决方案是将转换函数作为单独的参数传递:

let inline toUint32 x conv = 
  let bytes = conv x
  BitConverter.ToUInt32(bytes, 0)

toUint32 9999.99f BitConverter.GetBytes 
toUint32 9999.99 BitConverter.GetBytes 

这需要更多的输入,但很容易看到发生了什么。调用者只需要提供一个执行转换的函数 - 在典型情况下,只需要BitConverter.GetBytes

另一种方法(在另一个答案中已经讨论过)是使用一个稍微狡猾的技巧,让你指定更多花哨的静态约束;这消除了传递显式函数的需要,只要它对最终用户隐藏,它就可以缩短你的代码。

答案 1 :(得分:2)

如果您准备做一些不寻常的事情,可以使用静态解析的类型约束来推广该函数。

请注意,这不适用于其他.NET语言 - 静态解析的类型约束完全是F#编译器的一项功能。

type BitConvertible = 
    |BitConvertible
    static member Convert (conv : BitConvertible, flt : float) =
        System.BitConverter.GetBytes(flt)
    static member Convert (conv : BitConvertible, flt32 : float32) =
        System.BitConverter.GetBytes(flt32)

module BitConverter =
    let inline convertToBytes x  =
        ((^T or ^U) : (static member Convert : ^T * ^U -> byte[]) (BitConvertible, x))

然后你可以使用它......

let a = BitConverter.convertToBytes 16.0
let b = BitConverter.convertToBytes 27.0f