【问题标题】:Selecting BitConverter.ToXXX functions based on type根据类型选择 BitConverter.ToXXX 函数
【发布时间】:2013-10-22 11:53:53
【问题描述】:

我通常会尽量让我的问题更笼统,但这次我认为示例案例使问题更加清晰。我也是 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"

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

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

【问题讨论】:

    标签: generics f# higher-order-functions


    【解决方案1】:

    你需要转换最终值:

    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# 调用泛型函数。

    【讨论】:

    • +1 因为这很有帮助/教育意义,但是您确实更改了函数签名:)。不过,我想知道为什么。通过对象进行投射似乎也适用于我最初问题中的功能......即box BitConverter.ToInt16 :?&gt; (byte[] * int -&gt; 'a)。我也对你提到的那个编译时解决方案感兴趣。
    • 通过盒子投射也可以在这里工作(请参阅更新的解决方案)。签名是等效的,但也可以像原来一样省略参数,请参阅更新版本。
    • 这现在是 FsControl 的一部分:github.com/gmpl/FsControl/blob/…
    猜你喜欢
    • 2016-05-31
    • 2021-02-25
    • 2016-10-17
    • 1970-01-01
    • 2022-11-10
    • 2017-09-11
    • 1970-01-01
    • 2021-11-14
    • 2012-08-09
    相关资源
    最近更新 更多