泛型问题

时间:2011-10-20 20:53:59

标签: generics f#

为什么下面的代码没有编译?这是编译器错误还是语言功能?什么是最好的解决方法?

type A() as this =
    let a = this.GetTypedObject<int>()    // a
    let b = this.GetTypedObject<string>() // b

    member this.GetTypedObject<'T>() =
        Unchecked.defaultof<'T>

Unchecked.defaultof&LT;'T&GT;仅用于示例,可以使用任何函数或构造函数调用。

编译器说代码在(a)行变得不那么通用,并且拒绝编译行(b)。 我无法提供确切的编译器消息,因为我用俄语提供它们:)。

将方法GetTypedObject()转换为let绑定并删除&lt;'T&gt;最终得到另一个我不喜欢的编译器警告。我发现的唯一的问题是将GetTypedObject&lt;'T&gt;()移动到基类中并使其公开。提前谢谢......

2 个答案:

答案 0 :(得分:4)

请注意,您只需添加类型注释即可解决此问题:

type A() as this = 
    let a = this.GetTypedObject<int>()    // a 
    let b = this.GetTypedObject<string>() // b 

    member this.GetTypedObject<'T>() : 'T = 
                                   //^^^^
        Unchecked.defaultof<'T> 

当涉及类型推断的顺序时,首先读取成员签名,然后读取所有let和成员主体。通过将返回类型放在声明签名中,它将变为可见。

答案 1 :(得分:3)

由于类型推断从上到下工作,在遇到方法定义之前遇到GetTypedObject返回int并发现它应该是通用的(正如Brian指出的那样,成员在let绑定之前被读取......并且有一个更简单的解决方法。)我得到以下令人讨厌的错误:

  

“GetTypedObject”函数的使用与其他地方推断的类型不匹配。推断的函数类型是Test.A - &gt; Microsoft.FSharp.Core.unit - &gt; '一个。在这个使用点所需的功能类型是Test.A - &gt; Microsoft.FSharp.Core.unit - &gt; 'a此错误可能是由于'let rec'集合内或一组类中的泛型递归相关的限制。考虑为递归调用的目标提供完整类型签名,包括参数和返回类型的类型注释。

如果用法出现在方法定义之后,则可以正常工作。

type A() =
    member this.GetTypedObject<'T>() =
        Unchecked.defaultof<'T>

    member this.Test() =
      let a = this.GetTypedObject<int>()    // a
      let b = this.GetTypedObject<string>() // b
      ()

这是一种解决方法:

type A() =
  let getTypedObject() = Unchecked.defaultof<_>
  let a : int = getTypedObject()    // a
  let b : string = getTypedObject() // b

  member this.GetTypedObject<'T>() : 'T = getTypedObject()