0

我通常会尽量让我的问题更笼统,但这次我认为示例案例使问题更加清晰。我也是 F# 的新手,所以在这个阶段试图概括太多可能是一个错误:)

我想要实现的是创建一个函数,该函数返回BitConverter.ToXXX给定类型参数的适当函数。这是我尝试过的:

let FromBytes<'a> : (byte[] * int -> 'a) = 
  match typeof<'a> with
  | x when x = typeof<Int16> -> BitConverter.ToInt16
  | x when x = typeof<UInt16> -> BitConverter.ToUInt16
  | _ -> failwith "Unknown type"

但是,这会失败,因为编译器不理解类型保证匹配。

我确定我可以找到解决方法,但是有没有办法在不更改函数签名的情况下完成这项工作?

4

1 回答 1

4

您需要转换最终值:

let FromBytes<'a> : (byte[] * int -> 'a) = 
  match typeof<'a> with
  | x when x = typeof<Int16>  -> downcast (BitConverter.ToInt16  |> box)
  | x when x = typeof<UInt16> -> downcast (BitConverter.ToUInt16 |> box)
  | _ -> failwith "Unknown type"

这将在运行时检查类型并选择正确的大小写,在编译时使用静态约束也有一个技巧,但如果你正在学习它可能真的很混乱:

open System
type T = T with
    static member ($) (T, _: int16) = fun v s -> BitConverter.ToInt16 (v,s)
    static member ($) (T, _:uint16) = fun v s -> BitConverter.ToUInt16(v,s)
    static member ($) (T, _: int  ) = fun v s -> BitConverter.ToInt32 (v,s)
    static member ($) (T, _:uint32) = fun v s -> BitConverter.ToUInt32(v,s)

let inline fromBytes (value:byte[], startIndex:int) = 
    (T $ Unchecked.defaultof< ^R>) value startIndex : ^R

// usage
let (x:int   ) = fromBytes([|255uy;0uy;0uy;255uy|], 0)
let (y:uint16) = fromBytes([|255uy;0uy;0uy;255uy|], 0)

F# 编译器在调用站点内联所需的函数,您不能从 C# 调用泛型函数。

于 2013-10-22T12:59:12.443 回答