From 686d9926e34bd65e9db8bf466fac662a06f260d2 Mon Sep 17 00:00:00 2001 From: Kevin Ransom Date: Sat, 17 Nov 2018 01:46:56 -0800 Subject: [PATCH] Add new implementation of IEnumerable<_> for dict --- src/FSharp.Profiles.props | 1 + src/FSharpSource.Profiles.targets | 1 + .../FSharp.Core/fslib-extra-pervasives.fs | 30 ++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/FSharp.Profiles.props b/src/FSharp.Profiles.props index 915781c9534..3abfcb49be4 100644 --- a/src/FSharp.Profiles.props +++ b/src/FSharp.Profiles.props @@ -10,6 +10,7 @@ + $(DefineConstants);NETSTANDARD $(DefineConstants);NETSTANDARD1_6 $(DefineConstants);FX_NO_APP_DOMAINS $(DefineConstants);FX_NO_ARRAY_LONG_LENGTH diff --git a/src/FSharpSource.Profiles.targets b/src/FSharpSource.Profiles.targets index 9069ebdb955..3dc3cdd5fb3 100644 --- a/src/FSharpSource.Profiles.targets +++ b/src/FSharpSource.Profiles.targets @@ -13,6 +13,7 @@ + $(DefineConstants);NETSTANDARD $(DefineConstants);NETSTANDARD1_6 $(DefineConstants);FX_NO_APP_DOMAINS $(DefineConstants);FX_NO_ARRAY_LONG_LENGTH diff --git a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs index 63cb2d80718..b4271f4a267 100644 --- a/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs +++ b/src/fsharp/FSharp.Core/fslib-extra-pervasives.fs @@ -43,7 +43,9 @@ module ExtraTopLevelOperators = [] [>)>] type DictImpl<'SafeKey,'Key,'T>(t : Dictionary<'SafeKey,'T>, makeSafeKey : 'Key->'SafeKey, getKey : 'SafeKey->'Key) = - +#if NETSTANDARD + static let emptyEnumerator = (Array.empty> :> seq<_>).GetEnumerator() +#endif member x.Count = t.Count // Give a read-only view of the dictionary @@ -110,8 +112,34 @@ module ExtraTopLevelOperators = member s.GetEnumerator() = // We use an array comprehension here instead of seq {} as otherwise we get incorrect // IEnumerator.Reset() and IEnumerator.Current semantics. + // Coreclr has a bug with SZGenericEnumerators --- implement a correct enumerator. On desktop use the desktop implementation because it's ngened. +#if !NETSTANDARD let kvps = [| for (KeyValue (k,v)) in t -> KeyValuePair (getKey k, v) |] :> seq<_> kvps.GetEnumerator() +#else + let endIndex = t.Count + if endIndex = 0 then emptyEnumerator + else + let kvps = [| for (KeyValue (k,v)) in t -> KeyValuePair (getKey k, v) |] + let mutable index = -1 + let current () = + if index < 0 then raise <| InvalidOperationException(SR.GetString(SR.enumerationNotStarted)) + if index >= endIndex then raise <| InvalidOperationException(SR.GetString(SR.enumerationAlreadyFinished)) + kvps.[index] + + {new IEnumerator<_> with + member __.Current = current () + interface System.Collections.IEnumerator with + member __.Current = box(current()) + member __.MoveNext() = + if index < endIndex then + index <- index + 1 + index < endIndex + else false + member __.Reset() = index <- -1 + interface System.IDisposable with + member self.Dispose() = () } +#endif interface System.Collections.IEnumerable with member s.GetEnumerator() =