F#中的自定义IEnumerator

时间:2015-05-08 16:10:43

标签: f#

更多F#问题。我在下面有一个二进制阅读器的实现。我希望它像一个可枚举的序列一样工作。下面的代码给我以下错误,我一如既往地没有线索如何解决它。我有一个c#实现,我必须为.Current属性实现两个不同的覆盖。我想我必须在这里做同样的事,但不知道如何。一如既往,万分感谢您的帮助。

  

错误FS0366:未对Collections.IEnumerator.get_Current() : obj进行实施。请注意,必须在适当的interface声明下实施并列出所有界面成员,例如interface ... with member ...

namespace persisitence
open System.Collections.Generic
open System
open System.IO
type BinaryPersistenceIn<'T>(fn: string, serializer: ('T * BinaryReader) -> unit) as this =
    let stream_ = File.Open(fn, FileMode.Open, FileAccess.Read)
    let reader_ = new BinaryReader(stream_)
    [<DefaultValue>] val mutable current_ : 'T

    let eof() =
         stream_.Position = stream_.Length


    interface IEnumerator<'T> with

        member this.MoveNext() = 
            let mutable ret = eof()

            if stream_.CanRead && ret then
                serializer(this.current_, reader_)

            ret

        member this.Current
            with get() = this.current_ 

        member this.Dispose() =
            stream_.Close()
            reader_.Close()

        member this.Reset() = 
            stream_.Seek((int64) 0., SeekOrigin.Begin) |> ignore

3 个答案:

答案 0 :(得分:4)

正如@Richard指出的那样,你需要实施IEnumerator.Current 这是响应您的问题“如何做”的代码。这应该有效:

一些注意事项:(感谢@DaxFohl)

  • IEnumerator位于不同的命名空间中(请参阅代码)。
  • MoveNextReset实际上是IEnumerator的成员,而不是IEnumerator<'t>的成员,因此这是应该实施的地方。
  • Dispose但是,IEnumerator<'t>(惊喜!: - )

-

type BinaryPersistenceIn<'T>(fn: string, serializer: ('T * BinaryReader) -> unit) as this =
    ...    

    interface IEnumerator<'T> with
        ...
        member this.Current
            with get() = this.current_ 

    interface System.Collections.IEnumerator with
        member this.Current
            with get() = this.current_ :> obj
        member this.MoveNext() = ...
        member this.Reset() = ...

总而言之,我必须补充一点:你真的确定你想要实施IEnumerator吗?这是一个相当低调的事情,容易出错。为什么不使用序列计算表达式?

let binaryPersistenceSeq (fn: string) (serializer: BinaryReader -> 'T) = 
  seq {
    use stream_ = File.Open(fn, FileMode.Open, FileAccess.Read)
    use reader_ = new BinaryReader(stream_)

    let eof() = stream_.Position = stream_.Length

    while not eof() do
       if stream_.CanRead then
          yield serializer reader_
  }

答案 1 :(得分:1)

IEnumerator<T>扩展IEnumeratorIEnumerator具有Current类型的object属性。

您还需要与IEnumerator<T>.Current分开实施IEnumerator.Current

答案 2 :(得分:0)

这个版本的代码编译......至于它真的有用......会发现。

type BinaryPersistenceIn<'T>(fn: string, serializer: ('T * BinaryReader) -> unit) =
let stream_ = File.Open(fn, FileMode.Open, FileAccess.Read)
let reader_ = new BinaryReader(stream_)
[<DefaultValue>] val mutable current_ : 'T

let eof() =
     stream_.Position = stream_.Length


interface IEnumerator<'T> with

    member this.MoveNext() = 
        let mutable ret = eof()

        if stream_.CanRead && ret then
            serializer(this.current_, reader_)

        ret

    member this.Current
        with get() = this.current_ 

    member this.Dispose() =
        stream_.Close()
        reader_.Close()

    member this.Reset() = 
        stream_.Seek((int64) 0., SeekOrigin.Begin) |> ignore

    member this.Current
        with get() = this.current_ :> obj