Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,27 @@

namespace System.Collections.Generic
{
/// <summary>
/// Used internally to control behavior of insertion into a <see cref="Dictionary{TKey, TValue}"/>.
/// </summary>
internal enum InsertionBehavior : byte
{
/// <summary>
/// The default insertion behavior.
/// </summary>
None = 0,

/// <summary>
/// Specifies that an existing entry with the same key should be overwritten if encountered.
/// </summary>
OverwriteExisting = 1,

/// <summary>
/// Specifies that if an existing entry with the same key is encountered, an exception should be thrown.
/// </summary>
ThrowOnExisting = 2
}

[RelocatedType("System.Collections")]
[DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]
[DebuggerDisplay("Count = {Count}")]
Expand Down Expand Up @@ -196,13 +217,15 @@ public TValue this[TKey key]
}
set
{
Insert(key, value, false);
bool modified = TryInsert(key, value, InsertionBehavior.OverwriteExisting);
Debug.Assert(modified);
}
}

public void Add(TKey key, TValue value)
{
Insert(key, value, true);
bool modified = TryInsert(key, value, InsertionBehavior.ThrowOnExisting);
Debug.Assert(modified); // If there was an existing key and the Add failed, an exception will already have been thrown.
}

void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
Expand Down Expand Up @@ -353,7 +376,7 @@ private void Initialize(int capacity)
freeList = -1;
}

private void Insert(TKey key, TValue value, bool add)
private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior)
{
if (key == null)
{
Expand All @@ -372,13 +395,19 @@ private void Insert(TKey key, TValue value, bool add)
{
if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key))
{
if (add)
if (behavior == InsertionBehavior.OverwriteExisting)
{
entries[i].value = value;
version++;
return true;
}

if (behavior == InsertionBehavior.ThrowOnExisting)
{
throw new ArgumentException(SR.Format(SR.Argument_AddingDuplicate, key));
}
entries[i].value = value;
version++;
return;

return false;
}
#if FEATURE_RANDOMIZED_STRING_HASHING
collisionCount++;
Expand Down Expand Up @@ -417,6 +446,8 @@ private void Insert(TKey key, TValue value, bool add)
Resize(entries.Length, true);
}
#endif

return true;
}

public virtual void OnDeserialization(object sender)
Expand Down Expand Up @@ -455,7 +486,7 @@ public virtual void OnDeserialization(object sender)
{
throw new SerializationException(SR.Serialization_NullKey);
}
Insert(array[i].Key, array[i].Value, true);
Add(array[i].Key, array[i].Value);
}
}
else
Expand Down Expand Up @@ -556,20 +587,23 @@ public bool TryGetValue(TKey key, out TValue value)
return false;
}

// This is a convenience method for the internal callers that were converted from using Hashtable.
// Many were combining key doesn't exist and key exists but null value (for non-value types) checks.
// This allows them to continue getting that behavior with minimal code delta. This is basically
// TryGetValue without the out param
internal TValue GetValueOrDefault(TKey key)
// Method similar to TryGetValue that returns the value instead of putting it in an out param.
public TValue GetValueOrDefault(TKey key) => GetValueOrDefault(key, default(TValue));

// Method similar to TryGetValue that returns the value instead of putting it in an out param. If the entry
// doesn't exist, returns the defaultValue instead.
public TValue GetValueOrDefault(TKey key, TValue defaultValue)
{
int i = FindEntry(key);
if (i >= 0)
{
return entries[i].value;
}
return default(TValue);
return defaultValue;
}

public bool TryAdd(TKey key, TValue value) => TryInsert(key, value, InsertionBehavior.None);

bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
{
get { return false; }
Expand Down