@@ -30,65 +30,77 @@ module ExtraTopLevelOperators =
30
30
[<CompiledName( " CreateSet" ) >]
31
31
let set l = Collections.Set.ofSeq l
32
32
33
- [<CompiledName( " CreateDictionary" ) >]
34
- let dict l =
35
- // Use a dictionary (this requires hashing and equality on the key type)
36
- // Wrap keys in a StructBox in case they are null (when System.Collections.Generic.Dictionary fails).
37
- let t = new Dictionary< RuntimeHelpers.StructBox< 'Key>,_>( RuntimeHelpers.StructBox< 'Key>. Comparer)
33
+ let inline dictImpl ( comparer : IEqualityComparer < 'SafeKey >) ( makeSafeKey : 'Key -> 'SafeKey ) ( getKey : 'SafeKey -> 'Key ) ( l : seq < 'Key * 'T >) =
34
+ let t = Dictionary comparer
38
35
for ( k, v) in l do
39
- t.[ RuntimeHelpers.StructBox ( k ) ] <- v
36
+ t.[ makeSafeKey k ] <- v
40
37
let d = ( t :> IDictionary<_,_>)
41
38
let c = ( t :> ICollection<_>)
42
39
// Give a read-only view of the dictionary
43
40
{ new IDictionary< 'Key, 'T> with
44
41
member s.Item
45
- with get x = d.[ RuntimeHelpers.StructBox ( x ) ]
42
+ with get x = d.[ makeSafeKey x ]
46
43
and set x v = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)))
47
44
member s.Keys =
48
45
let keys = d.Keys
49
46
{ new ICollection< 'Key> with
50
47
member s.Add ( x ) = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
51
48
member s.Clear () = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
52
49
member s.Remove ( x ) = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
53
- member s.Contains ( x ) = keys.Contains( RuntimeHelpers.StructBox ( x ) )
50
+ member s.Contains ( x ) = keys.Contains( makeSafeKey x )
54
51
member s.CopyTo ( arr , i ) =
55
52
let mutable n = 0
56
53
for k in keys do
57
- arr.[ i+ n] <- k.Value
54
+ arr.[ i+ n] <- getKey k
58
55
n <- n + 1
59
56
member s.IsReadOnly = true
60
57
member s.Count = keys.Count
61
58
interface IEnumerable< 'Key> with
62
- member s.GetEnumerator () = ( keys |> Seq.map ( fun v -> v.Value ) ). GetEnumerator()
59
+ member s.GetEnumerator () = ( keys |> Seq.map getKey ). GetEnumerator()
63
60
interface System.Collections.IEnumerable with
64
- member s.GetEnumerator () = (( keys |> Seq.map ( fun v -> v.Value ) ) :> System .Collections .IEnumerable ). GetEnumerator () }
61
+ member s.GetEnumerator () = (( keys |> Seq.map getKey ) :> System .Collections .IEnumerable ). GetEnumerator () }
65
62
66
63
member s.Values = d.Values
67
64
member s.Add ( k , v ) = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)))
68
- member s.ContainsKey ( k ) = d.ContainsKey( RuntimeHelpers.StructBox ( k ) )
65
+ member s.ContainsKey ( k ) = d.ContainsKey( makeSafeKey k )
69
66
member s.TryGetValue ( k , r ) =
70
- let key = RuntimeHelpers.StructBox ( k )
67
+ let key = makeSafeKey k
71
68
if d.ContainsKey( key) then ( r <- d.[ key]; true ) else false
72
69
member s.Remove ( k : 'Key ) = ( raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated))) : bool)
73
70
interface ICollection< KeyValuePair< 'Key, 'T>> with
74
71
member s.Add ( x ) = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
75
72
member s.Clear () = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
76
73
member s.Remove ( x ) = raise ( NotSupportedException( SR.GetString( SR.thisValueCannotBeMutated)));
77
- member s.Contains ( KeyValue ( k , v )) = c.Contains( KeyValuePair<_,_>( RuntimeHelpers.StructBox ( k ) , v))
74
+ member s.Contains ( KeyValue ( k , v )) = c.Contains( KeyValuePair<_,_>( makeSafeKey k , v))
78
75
member s.CopyTo ( arr , i ) =
79
76
let mutable n = 0
80
77
for ( KeyValue( k, v)) in c do
81
- arr.[ i+ n] <- KeyValuePair<_,_>( k.Value , v)
78
+ arr.[ i+ n] <- KeyValuePair<_,_>( getKey k , v)
82
79
n <- n + 1
83
80
member s.IsReadOnly = true
84
81
member s.Count = c.Count
85
82
interface IEnumerable< KeyValuePair< 'Key, 'T>> with
86
83
member s.GetEnumerator () =
87
- ( c |> Seq.map ( fun ( KeyValue ( k , v )) -> KeyValuePair<_,_>( k.Value , v))) .GetEnumerator()
84
+ ( c |> Seq.map ( fun ( KeyValue ( k , v )) -> KeyValuePair<_,_>( getKey k , v))) .GetEnumerator()
88
85
interface System.Collections.IEnumerable with
89
86
member s.GetEnumerator () =
90
- (( c |> Seq.map ( fun ( KeyValue ( k , v )) -> KeyValuePair<_,_>( k.Value, v))) :> System.Collections.IEnumerable) .GetEnumerator() }
87
+ (( c |> Seq.map ( fun ( KeyValue ( k , v )) -> KeyValuePair<_,_>( getKey k, v))) :> System.Collections.IEnumerable) .GetEnumerator() }
88
+
89
+ // We avoid wrapping a StructBox, because under 64 JIT we get some "hard" tailcalls which affect performance
90
+ let dictValueType ( l : seq < 'Key * 'T >) = dictImpl HashIdentity.Structural< 'Key> id id l
91
+
92
+ // Wrap a StructBox around all keys in case the key type is itself a type using null as a representation
93
+ let dictRefType ( l : seq < 'Key * 'T >) = dictImpl RuntimeHelpers.StructBox< 'Key>. Comparer ( fun k -> RuntimeHelpers.StructBox k) ( fun sb -> sb.Value) l
91
94
95
+ [<CompiledName( " CreateDictionary" ) >]
96
+ let dict ( l : seq < 'Key * 'T >) =
97
+ #if FX_ ATLEAST_ 40
98
+ if typeof< 'Key>. IsValueType
99
+ then dictValueType l
100
+ else dictRefType l
101
+ #else
102
+ dictRefType l
103
+ #endif
92
104
93
105
let getArray ( vals : seq < 'T >) =
94
106
match vals with
0 commit comments