F#中的自定义IEnumerator [英] Custom IEnumerator in F#

查看:91
本文介绍了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.

错误FS0366:没有为Collections.IEnumerator.get_Current() : obj提供任何实现.请注意,所有接口成员都必须在相应的interface声明中实现并列出,例如interface ... with member ....

error FS0366: No implementation was given for Collections.IEnumerator.get_Current() : obj. Note that all interface members must be implemented and listed under an appropriate interface declaration, e.g. 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

推荐答案

正如@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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆