F# 中的自定义 IEnumerator
Custom IEnumerator in F#
更多 F# 问题。我在下面有一个二进制 reader 的实现。我希望它像可枚举序列一样工作。下面的代码给了我以下错误,我像往常一样不知道如何解决它。我有一个 c# 实现,其中我必须为 .Current
属性 实现两个不同的覆盖。我想我必须在这里做同样的事情,但不确定如何做。一如既往,提前一百万感谢您的帮助。
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
IEnumerator<T>
扩展 IEnumerator
并且 IEnumerator
有一个 Current
属性 类型 object
.
您还需要与 IEnumerator<T>.Current
分开实施 IEnumerator.Current
。
正如@Richard 指出的那样,您需要实施 IEnumerator.Current
.
这是回答您的问题 "how to do it" 的代码。这应该有效:
一些注意事项:(感谢@DaxFohl)
IEnumerator
在不同的命名空间中(见代码)。
MoveNext
和 Reset
实际上是 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_
}
这个版本的代码编译...至于它是否真的有效...会发现。
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
更多 F# 问题。我在下面有一个二进制 reader 的实现。我希望它像可枚举序列一样工作。下面的代码给了我以下错误,我像往常一样不知道如何解决它。我有一个 c# 实现,其中我必须为 .Current
属性 实现两个不同的覆盖。我想我必须在这里做同样的事情,但不确定如何做。一如既往,提前一百万感谢您的帮助。
error FS0366: No implementation was given for
Collections.IEnumerator.get_Current() : obj
. Note that all interface members must be implemented and listed under an appropriateinterface
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
IEnumerator<T>
扩展 IEnumerator
并且 IEnumerator
有一个 Current
属性 类型 object
.
您还需要与 IEnumerator<T>.Current
分开实施 IEnumerator.Current
。
正如@Richard 指出的那样,您需要实施 IEnumerator.Current
.
这是回答您的问题 "how to do it" 的代码。这应该有效:
一些注意事项:(感谢@DaxFohl)
IEnumerator
在不同的命名空间中(见代码)。MoveNext
和Reset
实际上是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_
}
这个版本的代码编译...至于它是否真的有效...会发现。
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