@@ -40,59 +40,95 @@ module ExtraTopLevelOperators =
4040let inline ICollection_Contains < 'collection , 'item when 'collection :> ICollection < 'item >> ( collection : 'collection ) ( item : 'item ) =
4141 collection.Contains item
4242
43- let inline dictImpl ( comparer : IEqualityComparer < 'SafeKey >) ( makeSafeKey : 'Key -> 'SafeKey ) ( getKey : 'SafeKey -> 'Key ) ( l : seq < 'Key * 'T >) =
43+ [<DebuggerDisplay( " Count = {Count}" ) >]
44+ [<DebuggerTypeProxy( typedefof< DictDebugView<_,_,_>>) >]
45+ type DictImpl < 'SafeKey , 'Key , 'T >( t :Dictionary < 'SafeKey , 'T >, makeSafeKey : 'Key -> 'SafeKey , getKey : 'SafeKey -> 'Key ) =
46+
47+ member x.Count = t.Count
48+
49+ // Give a read-only view of the dictionary
50+ interface IDictionary< 'Key, 'T> with
51+ member s.Item
52+ with get x= dont_ tail_ call( fun () -> t.[ makeSafeKey x])
53+ and set _ _ = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)))
54+ member s.Keys =
55+ let keys = t.Keys
56+ { new ICollection< 'Key> with
57+ member s.Add ( x ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
58+ member s.Clear () = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
59+ member s.Remove ( x ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
60+ member s.Contains ( x ) = t.ContainsKey( makeSafeKey x)
61+ member s.CopyTo ( arr , i ) =
62+ let mutable n = 0
63+ for kin keysdo
64+ arr.[ i+ n] <- getKey k
65+ n<- n+ 1
66+ member s.IsReadOnly = true
67+ member s.Count = keys.Count
68+ interface IEnumerable< 'Key> with
69+ member s.GetEnumerator () = ( keys|> Seq.map getKey). GetEnumerator()
70+ interface System.Collections.IEnumerablewith
71+ member s.GetEnumerator () = (( keys|> Seq.map getKey) :> System .Collections .IEnumerable ). GetEnumerator () }
72+
73+ member s.Values = upcast t.Values
74+ member s.Add ( _ , _ ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)))
75+ member s.ContainsKey ( k ) = dont_ tail_ call( fun () -> t.ContainsKey( makeSafeKey k))
76+ member s.TryGetValue ( k , r ) =
77+ let safeKey = makeSafeKey k
78+ if t.ContainsKey( safeKey) then ( r<- t.[ safeKey]; true ) else false
79+ member s.Remove ( _ : 'Key ) = ( raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated))) : bool)
80+
81+ interface IReadOnlyDictionary< 'Key, 'T> with
82+ member __.Item with get key= t.[ makeSafeKey key]
83+ member __.Keys = t.Keys|> Seq.map getKey
84+ member __.TryGetValue ( key , r ) =
85+ match t.TryGetValue( makeSafeKey key) with
86+ | false , _ -> false
87+ | true , value->
88+ r<- value
89+ true
90+ member __.Values = ( t:> IReadOnlyDictionary<_,_>) .Values
91+ member __.ContainsKey k = t.ContainsKey( makeSafeKey k)
92+
93+ interface ICollection< KeyValuePair< 'Key, 'T>> with
94+ member s.Add ( _ ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
95+ member s.Clear () = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
96+ member s.Remove ( _ ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
97+ member s.Contains ( KeyValue ( k , v )) = ICollection_ Contains t( KeyValuePair<_,_>( makeSafeKey k, v))
98+ member s.CopyTo ( arr , i ) =
99+ let mutable n = 0
100+ for ( KeyValue( k, v)) in tdo
101+ arr.[ i+ n] <- KeyValuePair<_,_>( getKey k, v)
102+ n<- n+ 1
103+ member s.IsReadOnly = true
104+ member s.Count = t.Count
105+
106+ interface IReadOnlyCollection< KeyValuePair< 'Key, 'T>> with
107+ member __.Count = t.Count
108+
109+ interface IEnumerable< KeyValuePair< 'Key, 'T>> with
110+ member s.GetEnumerator () =
111+ // We use an array comprehension here instead of seq {} as otherwise we get incorrect
112+ // IEnumerator.Reset() and IEnumerator.Current semantics.
113+ let kvps = [| for ( KeyValue( k, v)) in t-> KeyValuePair( getKey k, v) |] :> seq<_>
114+ kvps.GetEnumerator()
115+
116+ interface System.Collections.IEnumerablewith
117+ member s.GetEnumerator () =
118+ // We use an array comprehension here instead of seq {} as otherwise we get incorrect
119+ // IEnumerator.Reset() and IEnumerator.Current semantics.
120+ let kvps = [| for ( KeyValue( k, v)) in t-> KeyValuePair( getKey k, v) |] :> System.Collections.IEnumerable
121+ kvps.GetEnumerator()
122+
123+ and DictDebugView < 'SafeKey , 'Key , 'T >( d : DictImpl < 'SafeKey , 'Key , 'T >) =
124+ [<DebuggerBrowsable( DebuggerBrowsableState.RootHidden) >]
125+ member x.Items = Array.ofSeq d
126+
127+ let inline dictImpl ( comparer : IEqualityComparer < 'SafeKey >) ( makeSafeKey : 'Key -> 'SafeKey ) ( getKey : 'SafeKey -> 'Key ) ( l : seq < 'Key * 'T >) =
44128let t = Dictionary comparer
45- for ( k, v) in ldo
129+ for ( k, v) in ldo
46130 t.[ makeSafeKey k] <- v
47- // Give a read-only view of the dictionary
48- { new IDictionary< 'Key, 'T> with
49- member s.Item
50- with get x= dont_ tail_ call( fun () -> t.[ makeSafeKey x])
51- and set x v = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)))
52- member s.Keys =
53- let keys = t.Keys
54- { new ICollection< 'Key> with
55- member s.Add ( x ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
56- member s.Clear () = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
57- member s.Remove ( x ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
58- member s.Contains ( x ) = t.ContainsKey( makeSafeKey x)
59- member s.CopyTo ( arr , i ) =
60- let mutable n = 0
61- for kin keysdo
62- arr.[ i+ n] <- getKey k
63- n<- n+ 1
64- member s.IsReadOnly = true
65- member s.Count = keys.Count
66- interface IEnumerable< 'Key> with
67- member s.GetEnumerator () = ( keys|> Seq.map getKey). GetEnumerator()
68- interface System.Collections.IEnumerablewith
69- member s.GetEnumerator () = (( keys|> Seq.map getKey) :> System .Collections .IEnumerable ). GetEnumerator () }
70-
71- member s.Values = upcast t.Values
72- member s.Add ( k , v ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)))
73- member s.ContainsKey ( k ) = dont_ tail_ call( fun () -> t.ContainsKey( makeSafeKey k))
74- member s.TryGetValue ( k , r ) =
75- let safeKey = makeSafeKey k
76- if t.ContainsKey( safeKey) then ( r<- t.[ safeKey]; true ) else false
77- member s.Remove ( k : 'Key ) = ( raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated))) : bool)
78- interface ICollection< KeyValuePair< 'Key, 'T>> with
79- member s.Add ( x ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
80- member s.Clear () = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
81- member s.Remove ( x ) = raise( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
82- member s.Contains ( KeyValue ( k , v )) = ICollection_ Contains t( KeyValuePair<_,_>( makeSafeKey k, v))
83- member s.CopyTo ( arr , i ) =
84- let mutable n = 0
85- for ( KeyValue( k, v)) in tdo
86- arr.[ i+ n] <- KeyValuePair<_,_>( getKey k, v)
87- n<- n+ 1
88- member s.IsReadOnly = true
89- member s.Count = t.Count
90- interface IEnumerable< KeyValuePair< 'Key, 'T>> with
91- member s.GetEnumerator () =
92- ( t|> Seq.map( fun ( KeyValue ( k , v )) -> KeyValuePair<_,_>( getKey k, v))) .GetEnumerator()
93- interface System.Collections.IEnumerablewith
94- member s.GetEnumerator () =
95- (( t|> Seq.map( fun ( KeyValue ( k , v )) -> KeyValuePair<_,_>( getKey k, v))) :> System.Collections.IEnumerable) .GetEnumerator() }
131+ DictImpl( t, makeSafeKey, getKey)
96132
97133// We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance
98134let dictValueType ( l : seq < 'Key * 'T >) = dictImpl HashIdentity.Structural< 'Key> id id l
@@ -101,14 +137,24 @@ module ExtraTopLevelOperators =
101137let dictRefType ( l : seq < 'Key * 'T >) = dictImpl RuntimeHelpers.StructBox< 'Key>. Comparer( fun k -> RuntimeHelpers.StructBox k) ( fun sb -> sb.Value) l
102138
103139[<CompiledName( " CreateDictionary" ) >]
104- let dict ( keyValuePairs : seq < 'Key * 'T >) =
140+ let dict ( keyValuePairs : seq < 'Key * 'T >) : IDictionary < 'Key , 'T > =
141+ #if FX_ RESHAPED_ REFLECTION
142+ if ( typeof< 'Key>) .GetTypeInfo() .IsValueType
143+ #else
144+ if typeof< 'Key>. IsValueType
145+ #endif
146+ then dictValueType keyValuePairs:> _
147+ else dictRefType keyValuePairs:> _
148+
149+ [<CompiledName( " CreateReadOnlyDictionary" ) >]
150+ let readOnlyDict ( keyValuePairs : seq < 'Key * 'T >) : IReadOnlyDictionary < 'Key , 'T > =
105151#if FX_ RESHAPED_ REFLECTION
106152if ( typeof< 'Key>) .GetTypeInfo() .IsValueType
107153#else
108154if typeof< 'Key>. IsValueType
109155#endif
110- then dictValueType keyValuePairs
111- else dictRefType keyValuePairs
156+ then dictValueType keyValuePairs:> _
157+ else dictRefType keyValuePairs:> _
112158
113159let getArray ( vals : seq < 'T >) =
114160match valswith