Search code examples
f#ienumeratorseq

F#: Downcast seq to IEnumerator


Why is it that in F#, I can do this...

let s = seq { for i in 0 .. 4095 do yield i } :?> IEnumerator

... but this throws a System.InvalidCastException?

let s = Seq.init 4095 (fun i -> i) :?> IEnumerator

Solution

  • A sequence expression creates an object that implements IEnumerable<T> and IEnumerator<T>

    let s = seq { for i in 0 .. 4095 do yield i }
    printfn "%b" (s :? IEnumerable<int>) // true
    printfn "%b" (s :? IEnumerator<int>) // true
    

    But Seq.init does not:

    let s = Seq.init 4095 (fun i -> i)
    printfn "%b" (s :? IEnumerable<int>) // true
    printfn "%b" (s :? IEnumerator<int>) // false
    

    You could refactor your code to use IEnumerable<T> instead of IEnumerator since both constructs produce an IEnumerable<T>.

    Alternatively, if you really want an IEnumerator, you could simply call GetEnumerator to return an Enumerator from an Enumerable:

    let s = (Seq.init 4095 (fun i -> i)).GetEnumerator()
    printfn "%b" (s :? IEnumerable<int>) // false
    printfn "%b" (s :? IEnumerator<int>) // true