这是一个F#编译器错误吗? #3

时间:2011-02-07 21:05:46

标签: compiler-construction f# struct warnings

签名文件Foo.fsi

namespace FooBarSoftware
open System.Collections.Generic

[<Struct>]
type Foo<'T> =
     new: unit -> 'T Foo
     new: 'T   -> 'T Foo

     // doesn't exists in implementation!
     member public GetEnumerator: unit -> IEnumerator<'T>
     interface IEnumerable<'T>

实施文件Foo.fs

namespace FooBarSoftware
open System.Collections
open System.Collections.Generic

[<Struct>]
type Foo<'T> =
     val offset: int
     new (x:'T) = { offset = 1 }

     interface IEnumerable<'T> with
        member this.GetEnumerator() = null :> IEnumerator<'T>
        member this.GetEnumerator() = null :> IEnumerator

这个编译很好,但有警告FS0314

  

签名和实现中的类型定义不兼容,因为字段偏移存在于实现中但不存在于签名中。结构类型现在必须在类型的签名中显示其字段,但字段可能仍标记为“私有”或“内部”。

当我运行这样的代码时,我有MethodMissingException

let foo = FooBarSoftware.Foo<int>() // <==

// System.MethodMissingException:
// Method not found: 'Void FooBarSoftware.Foo~1..ctor()'

此外,如果我使用其他ctor并调用GetEnumerator()方法:

let foo = FooBarSoftware.Foo<int>(1)
let e = foo.GetEnumerator() // <==

// System.MethodMissingException:
// Method not found: 'System.Collections.Generic.IEnumerator`1<!0>
// FooBarSoftware.Foo`1.GetEnumerator()'.

这是一个编译器错误,它允许在收到FS0314警告后编译接口而不实现吗?

Microsoft (R) F# 2.0 build 4.0.30319.1

2 个答案:

答案 0 :(得分:3)

对我来说看起来像个错误。以下运行正常。

签名文件Foo.fsi

namespace FooBarSoftware
open System.Collections.Generic

//[<Struct>]
type Foo<'T> =
     new: unit -> 'T Foo
     new: 'T   -> 'T Foo

     // doesn't exists in implementation!
     //member public GetEnumerator: unit -> IEnumerator<'T>

     interface IEnumerable<'T>

实施文件Foo.fs

namespace FooBarSoftware
open System.Collections
open System.Collections.Generic

//[<Struct>]
type Foo<'T> =
    val offset: int
    new () = { offset = 1 }
    new (x:'T) = { offset = 1 }

    //member this.GetEnumerator() = null :> IEnumerator<'T>

    interface IEnumerable<'T> with
        member this.GetEnumerator() = null :> IEnumerator<'T>
        member this.GetEnumerator() = null :> IEnumerator

测试文件test.fs

module test

let foo = FooBarSoftware.Foo<int>() 
let bar = FooBarSoftware.Foo<int>(1)
let e = foo :> seq<_>

反射器还会显示代码中缺少.ctor()

Missing Default COnstructor

答案 1 :(得分:2)

你班上真的没有GetEnumerator。您应该在F#中阅读有关接口和继承的更多信息: http://msdn.microsoft.com/en-us/library/dd233207.aspx http://msdn.microsoft.com/en-us/library/dd233225.aspx

如果从.fsi文件中删除GetEnumerator行,则应该起作用:

let foo = FooBarSoftware.Foo<int>(1)
let e = (foo :> IEnumerable<_>).GetEnumerator()