Signature file 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>
Implementation file 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
This compiles fine, but with warning FS0314
:
The type d开发者_JAVA技巧efinitions in the signature and implementation are not compatible because the field offset was present in the implementation but not in the signature. Struct types must now reveal their fields in the signature for the type, though the fields may still be labelled 'private' or 'internal'.
When I run the code like that, I've got MethodMissingException
:
let foo = FooBarSoftware.Foo<int>() // <==
// System.MethodMissingException:
// Method not found: 'Void FooBarSoftware.Foo~1..ctor()'
Also if I use other ctor and call GetEnumerator()
method:
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()'.
Is this an compiler bug, that allows to compile interface without implementation after getting an FS0314
warning?
Microsoft (R) F# 2.0 build 4.0.30319.1
Looks like a bug to me. The following runs fine.
Signature file 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>
Implementation file 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 file test.fs
:
module test
let foo = FooBarSoftware.Foo<int>()
let bar = FooBarSoftware.Foo<int>(1)
let e = foo :> seq<_>
.
Reflector also shows .ctor()
missing from your code.
You really don't have GetEnumerator in your class. You should read more about interfaces and inheritance in F#: http://msdn.microsoft.com/en-us/library/dd233207.aspx http://msdn.microsoft.com/en-us/library/dd233225.aspx
If you remove the GetEnumerator line from the .fsi file, this should work:
let foo = FooBarSoftware.Foo<int>(1)
let e = (foo :> IEnumerable<_>).GetEnumerator()
精彩评论