从f#我试图使用成员约束在C#定义的对象上调用函数。由于c#成员函数采用多个参数,因此f#编译器将其视为元组,但在应用泛型成员约束时,我得到一个错误,该函数接受4个参数,但我只提供了一个。
我尝试从参数中形成元组,或者只是采用预先设置的参数集,但两者都给出了相同的错误。我想我必须错误地定义我的成员约束,但是没有很多带有多个参数的成员约束的例子。
let inline wrapForDecode (buffer:DirectBuffer) (offset:int) (blockLen:uint16) (version:uint16) : ^a =
let msg = new ^a()
(^a : (member WrapForDecode : (DirectBuffer*int*int*int)->unit) msg, (buffer, offset, (int blockLen), (int version)))
msg
let inline wrapForDecode2 (args :DirectBuffer*int*int*int) : ^a =
let msg = new ^a()
(^a : (member WrapForDecode : (DirectBuffer*int*int*int)->unit) (msg, args))
msg
原始的WrapForDecode成员函数在c#中定义:
public void WrapForDecode(DirectBuffer buffer, int offset, int actingBlockLength, int actingVersion) {...}
当我尝试调用该函数时,对于wrapForDecode或wrapForDecode2,我得到以下错误。
The member or object constructor 'WrapForDecode' takes 4 argument(s) but is here given 1. The required signature is 'MDInstrumentDefinitionFuture27.WrapForDecode(buffer: DirectBuffer, offset: int, actingBlockLength: int, actingVersion: int) : unit'.
答案 0 :(得分:6)
如果将WrapForDecode
的参数类型从(DirectBuffer*int*int*int)
更改为DirectBuffer*int*int*int
,则第一个内联方法将编译:
let inline wrapForDecode (buffer:string)
(offset:int)
(blockLen:uint16)
(version:uint16)
: ^a =
let msg = new ^a()
(^a : (member WrapForDecode : string * int * int * int -> unit)
msg,
buffer,
offset,
(int blockLen),
(int version))
msg
type foo () =
member this.WrapForDecode (a : string, b: int, c: int, d:int) =
()
let x : foo = wrapForDecode "asd" 1 2us 3us
在普通的F#代码中,两个签名是等价的 - 所有方法都采用一个参数,并编写一个带有arity>的函数。 1它必须是咖喱或者是一个有争议的论点。
然而,这不是CLI的工作方式 - 在C#/ VB.Net中,foo1(x : bar, y : baz)
与foo2(xy : Tuple<bar, baz>)
具有不同的签名。
通常,F#编译器会自动在两种样式之间进行转换,因此当从F#访问非F#.NET代码时,您会看到这两种方法都采用了一个tupled参数。
但是静态解析的成员约束是F#的一个复杂且相对边缘的特性,所以当用这种方式调用方法时,似乎没有或不能执行这种自动转换。
(感谢@ildjarn指出了这种差异的来源)