Skip to content

Commit b62168a

Browse files
committed
Improved FallbackDictionary operations and allocations.
1 parent f241b02 commit b62168a

2 files changed

Lines changed: 62 additions & 12 deletions

File tree

src/Autofac/Util/FallbackDictionary.cs

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,22 @@ public int Count
5555
{
5656
get
5757
{
58-
return Keys.Count;
58+
var count = _localValues.Count;
59+
60+
if (_parent.Count == 0)
61+
{
62+
return count;
63+
}
64+
65+
foreach (var key in _parent.Keys)
66+
{
67+
if (!_localValues.ContainsKey(key))
68+
{
69+
count++;
70+
}
71+
}
72+
73+
return count;
5974
}
6075
}
6176

@@ -84,7 +99,7 @@ public bool IsReadOnly
8499
/// but it is guaranteed to be the same order as the corresponding values in the <see cref="ICollection{TKey}"/>
85100
/// returned by the <see cref="Values"/> property.
86101
/// </remarks>
87-
public ICollection<TKey> Keys => GetOrderedKeysSnapshot();
102+
public ICollection<TKey> Keys => GetMergedKeysSnapshot();
88103

89104
/// <summary>
90105
/// Gets an <see cref="ICollection{TKey}"/> containing the values of the dictionary.
@@ -101,7 +116,7 @@ public ICollection<TValue> Values
101116
{
102117
get
103118
{
104-
var keys = GetOrderedKeysSnapshot();
119+
var keys = GetMergedKeysSnapshot();
105120
var values = new TValue[keys.Count];
106121
for (var i = 0; i < keys.Count; i++)
107122
{
@@ -222,7 +237,7 @@ public bool Contains(KeyValuePair<TKey, TValue> item)
222237
[SuppressMessage("CA1841", "CA1841", Justification = "False positive. This isn't a standard set of keys like other dictionaries.")]
223238
public bool ContainsKey(TKey key)
224239
{
225-
return Keys.Contains(key);
240+
return _localValues.ContainsKey(key) || _parent.ContainsKey(key);
226241
}
227242

228243
/// <summary>
@@ -237,8 +252,26 @@ public bool ContainsKey(TKey key)
237252
/// </param>
238253
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
239254
{
240-
var resolved = (ICollection<KeyValuePair<TKey, TValue>>)new Dictionary<TKey, TValue>(this);
241-
resolved.CopyTo(array, arrayIndex);
255+
if (array == null)
256+
{
257+
throw new ArgumentNullException(nameof(array));
258+
}
259+
260+
if (arrayIndex < 0 || arrayIndex > array.Length)
261+
{
262+
throw new ArgumentOutOfRangeException(nameof(arrayIndex));
263+
}
264+
265+
if (array.Length - arrayIndex < Count)
266+
{
267+
throw new ArgumentException(FallbackDictionaryResources.InsufficientArraySpace, nameof(array));
268+
}
269+
270+
var index = arrayIndex;
271+
foreach (var kvp in EnumerateKeyValuePairs())
272+
{
273+
array[index++] = kvp;
274+
}
242275
}
243276

244277
/// <summary>
@@ -249,10 +282,7 @@ public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
249282
/// </returns>
250283
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
251284
{
252-
foreach (var key in GetOrderedKeysSnapshot())
253-
{
254-
yield return new KeyValuePair<TKey, TValue>(key, this[key]);
255-
}
285+
return EnumerateKeyValuePairs().GetEnumerator();
256286
}
257287

258288
/// <summary>
@@ -326,7 +356,7 @@ IEnumerator IEnumerable.GetEnumerator()
326356
/// Gets the list of correctly ordered unique keys from the local and parent dictionaries.
327357
/// </summary>
328358
/// <returns>A new list containing the ordered unique set of keys.</returns>
329-
private List<TKey> GetOrderedKeysSnapshot()
359+
private List<TKey> GetMergedKeysSnapshot()
330360
{
331361
var keys = new List<TKey>(_localValues.Count + _parent.Count);
332362
keys.AddRange(_localValues.Keys);
@@ -339,7 +369,24 @@ private List<TKey> GetOrderedKeysSnapshot()
339369
}
340370
}
341371

342-
keys.Sort();
343372
return keys;
344373
}
374+
375+
private IEnumerable<KeyValuePair<TKey, TValue>> EnumerateKeyValuePairs()
376+
{
377+
foreach (var kvp in _localValues)
378+
{
379+
yield return kvp;
380+
}
381+
382+
foreach (var parentKvp in _parent)
383+
{
384+
if (_localValues.ContainsKey(parentKvp.Key))
385+
{
386+
continue;
387+
}
388+
389+
yield return parentKvp;
390+
}
391+
}
345392
}

src/Autofac/Util/FallbackDictionaryResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,4 +120,7 @@
120120
<data name="DuplicateItem" xml:space="preserve">
121121
<value>Item has already been added with key '{0}'.</value>
122122
</data>
123+
<data name="InsufficientArraySpace" xml:space="preserve">
124+
<value>The destination array does not have enough space to copy the items.</value>
125+
</data>
123126
</root>

0 commit comments

Comments
 (0)