You can write a helper function:

1
2
3
4
5
6
7
8
9
module SCG = System.Collections.Generic
module COL = System.Collections

let EnumeratorToEnumerable (e: 'a SCG.IEnumerator) =
    { new SCG.IEnumerable<'a> with
          member x.GetEnumerator () = e
        interface COL.IEnumerable with
          member x.GetEnumerator () = (e:>COL.IEnumerator)
    }

But this code is not safe enough - it depends on the enumerator mutable state.

1
2
3
4
  let etor = ([ 1;2;3 ] :> int seq).GetEnumerator()
  let enu = EnumeratorToEnumerable etor
  etor.MoveNext() |> ignore
  enu |> Seq.iter System.Console.WriteLine

The sample code above modifies the enumerator state after creating the IEnumerable object. The result is that iterating over the sequence loses the first item. It is possible to modify the EnumeratorToEnumerable function so that it calls IEnumerator.Reset() but this may also affect another code which relies on the source IEnumerator. Unfortunately, .NET IEnumerator interface is not cloneable by default, but if you use the IEnumerator of your own, you may add ICloneable support and rewrite the helper function code like this:

1
2
3
4
5
6
7
8
9
10
11
12
let EnumeratorToEnumerable2 (etor: 'a when 'a :> SCG.IEnumerator<'b> and 'a:> ICloneable) =
    { new SCG.IEnumerable<'b> with
          member x.GetEnumerator () = 
            let e = etor.Clone() :?> SCG.IEnumerator<'b>
            e.Reset()
            e
        interface COL.IEnumerable with
          member x.GetEnumerator () = 
            let e = etor.Clone() :?> COL.IEnumerator
            e.Reset()
            e
    }

But a better solution would be following the standard .NET practice with both IEnumerable/IEnumerator where IEnumerable creates a fresh IEnumerator with proper state.

By on 5/16/2008 2:53 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper