从F#调用重载的C#方法

jun*_*iro 4 c# f#

在SO上有一些类似的问题,但我似乎无法找到我正在寻找的东西.

有一个C#库(OpenCVSharp)声明一个像这样的重载方法:

public static void CalcHist(Mat[] images, 
            int[] channels, InputArray mask,
            OutputArray hist, int dims, int[] histSize,
            Rangef[] ranges, bool uniform = true, bool accumulate = false)
{
           ....
}

public static void CalcHist(Mat[] images,
            int[] channels, InputArray mask,
            OutputArray hist, int dims, int[] histSize,
            float[][] ranges, bool uniform = true, bool accumulate = false)
{
    ....
}
Run Code Online (Sandbox Code Playgroud)

即仅仅通过"范围"参数的类型来改变.

我似乎无法调用此方法,即使使用tupled参数样式,包括可选参数和添加一大堆类型注释:

let images = [|new Mat()|] 
let hist = OutputArray.Create(new Mat());
let hdims = [|256|];
let ranges = [| new Rangef(0.f,256.f) |];
Cv2.CalcHist<Mat [] * int [] * InputArray * OutputArray * int * int [] * Rangef [] * bool * bool>
            (images,
            [|0|],
            null,
            hist,
            1,
            hdims,
            ranges,
            true,
            false)
Run Code Online (Sandbox Code Playgroud)

错误是"错误4成员或对象构造函数'CalcHist'从这个代码位置无法访问9个参数.方法'CalcHist'的所有可访问版本都有9个参数"

有什么办法我可以用F#调用这个方法吗?

Fyo*_*kin 5

您选择用于指定参数类型的语法实际上不适用于指定参数类型.该语法用于指定泛型函数或类型的泛型参数:

let imGeneric<'t, 'u> (x: 't, y: 'u) = ...
let callGeneric = imGeneric<int, string> (5, "abc")
Run Code Online (Sandbox Code Playgroud)

但是,当然,大多数情况下,F#编译器可以为您推断泛型参数,因此您不需要经常明确指定它们:

let imGeneric (x, y) = ...
let callGeneric = imGeneric (5, "abc")
Run Code Online (Sandbox Code Playgroud)

你的Cv2.CalcHist方法通用.删除泛型参数,它应该工作正常:

Cv2.CalcHist( images, [|0|], null, hist, 1, hdims, ranges, true, false )
Run Code Online (Sandbox Code Playgroud)

上面的工作,因为编译器已经知道它ranges有类型Rangef [],所以它可以选择正确的重载而无需你做任何额外的工作.

但有时真的有必要明确指定一些(或所有)参数的类型.在这些情况下,您可以正确指定类型:

Cv2.CalcHist( 
   images, [|0|], null, hist, 1, hdims, 
   (ranges : Rangef []), 
   true, false )
Run Code Online (Sandbox Code Playgroud)

注意附加的括号(ranges : Rangef []).没有它们,类型注释不仅适用于ranges,而且适用于整个元组images, [|0|], null, hist, 1, hdims, ranges,这将导致编译时错误,因为这样的元组显然不能有类型Rangef [].

或者,您可以在调用之前的任何位置修复值的类型:

let ranges: Rangef [] = getRanges()
Cv2.CalcHist( images, [|0|], null, hist, 1, hdims, ranges, true, false )
Run Code Online (Sandbox Code Playgroud)

这将产生同样的效果.编译器实际上只需要知道类型,它并不关心它定义的确切位置,只要它在需要它之前.