我需要一个小型实用函数,从8字节数组生成校验和。
这本身很简单,但在C#中,我不能使用byte Checksum(byte[8] input)
作为方法声明-我无法指定数组大小,因此必须使用可以是任何大小的byte[],然后在方法体中,我需要检查输入不为空且长度== 8。
我想知道F#是否能够做到这一点?我听说F#有更多选项来限制函数的可接受参数(例如,辨别联合)?
当然,在这个微不足道的例子中,F#会过度杀伤,但我很好奇。
byte[]
参数在我看来是可以的;唯一要做的更改是考虑传递起始偏移量(因为我经常发现自己从 byte[]
的开头开始工作——但这取决于上下文)。long
(或者由于负数的右移而更好: ulong
)。您总是知道它的长度恰好为 8 个字节,并且它还避免了一些查找。byte*
和 ulong*
的不安全转换在两种格式之间切换。我认为正确的做法是创建一个包装byte[8]的type
,并将其用作参数。
话虽如此,我可以考虑使用活动模式,但似乎有点矫枉过正:
let (|Is8|NotIs8|) (input : byte[]) = if input.Length = 8 then Is8 else NotIs8
let testFunction (a : 'T[]) =
match a with
| Is8 -> printfn "yes it is 8 in size"
| NotIs8 -> printfn "it is not 8 in size"
两种语言都不能指定函数接受特定长度的数组。这个问题在于要检查调用者是否实际提供了具有该长度的数组相当困难。可以通过直接创建 new byte[8]
时检查,但其他所有情况都需要一些巧妙的技巧。
这部分工作由Code Contracts完成,它是一种用于附加检查的工具,可安装到Visual Studio中并与C#和F#一起使用。它允许你编写类似如下的代码:
byte CheckSum(byte[] data) {
Contract.Requires(data != null);
Contract.Requires(data.Length == 8);
// Implementation
}
代码合约配备了一个工具,可以在编译时警告您调用大小不正确的数组时调用CheckSum
。它还可以生成运行时检查(当无法静态确定调用是否正确时)。