使用TryParse进行重载决策

7

我们有一个函数,将类似 Int32.TryParse 的方法由使用 byref 改为使用 Option 作为返回值。

let inline ToOptionFunc refFunction x =
    match refFunction x with
    | true, value  -> Some value
    | false, _     -> None

在.NET Core中,使用TryParse的新重载方式会导致类似这样的代码无法编译:

let Int32TryParse (x:string) =
     ToOptionFunc Int32.TryParse x // A unique overload for method 'TryParse' could not be determined (...)

我尝试了很多方法,最终意外地通过这种方式解决了问题:

let Int32TryParse (x:string) =
     x |> ToOptionFunc Int32.TryParse

我不理解为什么这段代码可以编译通过而前面的不能。

你为什么要转换 Int32.TryParse?它已经可以像你第一个代码块中那样直接使用了。 - TeaDrivenDev
1
所以它能更好地与F#代码配合使用。例如: tryParse >> Option.map - Asik
啊,抱歉,我漏掉了那部分。 - TeaDrivenDev
1个回答

11
在 .NET Core 中,Int32.TryParse 函数有一些额外的重载 - 它可以解析 stringReadOnlySpan<char>。原始代码停止工作,因为编译器不知道您想使用哪个重载。
在没有管道的版本中,编译器需要对 ToOptionFunc Int32.TryParse x 进行类型检查。它从左到右进行处理,当它到达 Int32.TryParse 时,它还不知道 x(它具有类型注释,将其限制为 string),而不知道 x,它无法确定您需要哪个 TryParse
在有管道的版本中,编译器需要对 x |> ToOptionFunc Int32.TryParse 进行类型检查。它从左到右进行处理,并知道 xstring,因此它推断传递给 ToOptionFunc 的函数也必须是取 string 的函数,并且当它检查 Int32.TryParse 时,它已经可以唯一确定重载。
总之,管道对于指导类型检查非常有用!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接