本文介绍了F#中的自定义IEnumerator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更多F#问题.我在下面有一个二进制阅读器的实现.我希望它像一个可枚举的序列一样工作.下面的代码为我提供了以下错误,并且与往常一样,我不知道如何解决该错误.我有一个c#实现,我必须为.Current属性实现两个不同的替代.我想我必须在这里做同样的事情,但不确定如何做.与往常一样,先感谢您提供一百万美元的帮助.

More F# questions. I have the implementation of a binary reader below. I want it to work like an enumerable sequence. The code below gives me the following error and I have as usual no clue how to resolve it. I have a c# implementation where I had to implement two different overrides for .Current property. I guess I have to do the same here but not sure how. As always, thanks a million in advance for your help.

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

推荐答案

正如@Richard指出的那样,您需要实现IEnumerator.Current.
这是针对您的问题如何做"的代码.这应该起作用:

As @Richard pointed out, you need to implement IEnumerator.Current.
Here's code in response to your question "how to do it". This should work:

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

A few notes: (thanks to @DaxFohl)

  • IEnumerator在不同的命名空间中(请参见代码).
  • MoveNextReset实际上是IEnumerator的成员,而不是IEnumerator<'t>,因此应该在其中实现.
  • 但是,
  • DisposeIEnumerator<'t>上(惊奇!:-)
  • IEnumerator is in different namespace (see code).
  • MoveNext and Reset are really members of IEnumerator, not IEnumerator<'t>, so that's where they should be implemented.
  • Dispose, however, is on IEnumerator<'t> (surprise! :-)

-

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的吗?这是一个相当低级的事情,容易出错.为什么不使用序列计算表达式呢?

And in conclusion, I must add this: are you really sure you want to implement IEnumerator? This is a rather low-lever thing, easy to get wrong. Why not use a sequence computation expression instead?

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_
  }

这篇关于F#中的自定义IEnumerator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-23 17:19