[英]Custom IEnumerator in F#
More F# questions. 更多F#问题。 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 ac# implementation where I had to implement two different overrides for
.Current
property. 我有ac#implementation,我必须为
.Current
属性实现两个不同的覆盖。 I guess I have to do the same here but not sure how. 我想我必须在这里做同样的事,但不知道如何。 As always, thanks a million in advance for your help.
一如既往,万分感谢您的帮助。
error FS0366: No implementation was given for
Collections.IEnumerator.get_Current() : obj
.错误FS0366:没有为
Collections.IEnumerator.get_Current() : obj
。 Note that all interface members must be implemented and listed under an appropriateinterface
declaration, eginterface ... with member ...
.请注意,必须在适当的
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
As @Richard pointed out, you need to implement IEnumerator.Current
. 正如@Richard所指出的,你需要实现
IEnumerator.Current
。
Here's code in response to your question "how to do it". 这是响应您的问题“如何做”的代码。 This should work:
这应该工作:
A few notes: (thanks to @DaxFohl) 一些注意事项:(感谢@DaxFohl)
IEnumerator
is in different namespace (see code). IEnumerator
位于不同的命名空间中(参见代码)。 MoveNext
and Reset
are really members of IEnumerator
, not IEnumerator<'t>
, so that's where they should be implemented. MoveNext
和Reset
实际上是IEnumerator
成员,而不是IEnumerator<'t>
,因此它们应该被实现。 Dispose
, however, is on IEnumerator<'t>
(surprise! :-) 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() = ...
And in conclusion, I must add this: are you really sure you want to implement IEnumerator
? 最后,我必须补充一点:你真的确定要实现
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_
}
IEnumerator<T>
extends IEnumerator
and IEnumerator
has a Current
property of type object
. IEnumerator<T>
扩展IEnumerator
, IEnumerator
具有object
类型的Current
属性。
You need to also implement IEnumerator.Current
separately from IEnumerator<T>.Current
. 您还需要与
IEnumerator<T>.Current
分别实现IEnumerator.Current
。
This version of the code compiles... as to does it really work.. will find out. 这个版本的代码编译...至于它真的有用..会发现。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.