问题描述
更多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
在不同的命名空间中(请参见代码). -
MoveNext
和Reset
实际上是IEnumerator
的成员,而不是IEnumerator<'t>
,因此应该在其中实现. 但是, -
Dispose
在IEnumerator<'t>
上(惊奇!:-)
IEnumerator
is in different namespace (see code).MoveNext
andReset
are really members ofIEnumerator
, notIEnumerator<'t>
, so that's where they should be implemented.Dispose
, however, is onIEnumerator<'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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!