该参数的使用方式将其限制为始终为DerrivedType

时间:2017-10-16 19:37:55

标签: f# c#-to-f#

您好,我刚刚开始使用F#进行编程,并且遇到类型问题。 我有这个功能:

    member private this.UpdateStats<'T when 'T :> StatisticsBase>(passed: bool, stats: 'T) =
        //more stuff..
        stats

我这样称呼它:

this.UpdateStats<GroupStats>(true, GroupStats(Id = Guid.NewGuid()))

编译器说:

enter image description here     该参数的使用方式将其限制为始终为GroupStats。

GroupStats继承自StatisticsBase。我该怎么做才能使该函数可用于从StatisticsBase继承的所有实体?

类型:

[<AllowNullLiteral>] 
type StatisticsBase() =
    member val Id = String.Empty with get,set

[<AllowNullLiteral>] 
type GroupStats() =
    inherit Stats()

StatisticsBase实际上是继承自C#类型并在存储库中使用,但我可以使用上面的代码重现错误

1 个答案:

答案 0 :(得分:3)

经过多次来回,我们已经能够确定您的实际非工作代码是这样的(未来提示:提供更多信息):

type SomeType() =
    member this.M2() =
        this.M<GroupStats>(true, GroupStats())

    member private this.M<'T when 'T :> Stats>(x: bool, t: 'T) =
        t

此代码确实会产生所描述的错误。这是因为F#类型推断从上到下,从左到右。但是有一个例外:类(和其他相互重新定义的组)获得两次类型推断 - 第一个签名,然后是主体。

当编译器首次遇到M2的主体时,它确定方法M必须返回GroupStats。稍后,当编译器遇到M的主体时,它会看到M的返回值与参数t相同,这意味着M必须返回{ {1}}。但是,由于编译器已经知道,通过检查'T的正文,M2必须返回M,因此GroupStats必须是'T

如果在GroupStats之前定义M,则不会发生这种情况:在这种情况下,类型推断将首先遇到M2的主体并正确确定其返回类型为{{} 1}},然后将与M的正文匹配,这将没有问题。

根据以上内容,可以制定两个解决方案:首先,您可以在'T之前定义M2。其次,您可以只显式指定M的返回类型:

M2

这样,它的返回类型将在第一次传递后被识别,并且问题消失。