我通常会尝试使我的问题更通用,但这次我认为示例案例使问题更加清晰。我也是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"
但是,这会失败,因为编译器不理解类型是否保证匹配。
我确信我可以找到解决方法,但有没有办法在不更改功能签名的情况下完成这项工作?
答案 0 :(得分: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#调用泛型函数。