Skip to content

Commit

Permalink
Add a polyfill for Dictionary{TKey,}.TryAdd (#211)
Browse files Browse the repository at this point in the history
  • Loading branch information
jahav authored Sep 2, 2024
1 parent d2e4048 commit 139d797
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 3 deletions.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,7 @@ The class `Polyfill` includes the following extension methods:

#### Dictionary<TKey,TValue>

* `Boolean TryAdd<TKey, TValue>(TKey, TValue)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.tryadd)
* `Boolean Remove<TKey, TValue>(TKey, TValue&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.remove)


Expand Down
2 changes: 2 additions & 0 deletions src/Consume/Consume.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ class Consume
dictionary.GetValueOrDefault("key");
dictionary.GetValueOrDefault("key", "default");

dictionary.TryAdd("key", "value");

var concurrentDictionary = new ConcurrentDictionary<string, int>();

var value = concurrentDictionary.GetOrAdd("Hello", (_, arg) => arg.Length, "World");
Expand Down
33 changes: 32 additions & 1 deletion src/Polyfill/Polyfill_Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,37 @@ static partial class Polyfill
public static ReadOnlyDictionary<TKey, TValue> AsReadOnly<TKey, TValue>(this IDictionary<TKey, TValue> target) =>
new(target);
#endif

#if NETFRAMEWORK || NETSTANDARD2_0

/// <summary>
/// Attempts to add the specified key and value to the dictionary.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add. It can be <see langword="null"/>.</param>
/// <returns><c>true</c> if the key/value pair was added to the dictionary successfully; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
[Link("https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.dictionary-2.tryadd")]
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> target, TKey key, TValue value)
{
if (key is null)
{
throw new ArgumentNullException(nameof(key));
}

if (!target.ContainsKey(key))
{
target.Add(key, value);
return true;
}

return false;
}

#endif

#if NETFRAMEWORK || NETSTANDARD2_0 || NETCOREAPP2X

/// <summary>
/// Removes the value with the specified key from the <see cref="Dictionary{TKey,TValue}"/>, and copies the element
/// to the value parameter.
Expand All @@ -44,5 +74,6 @@ public static bool Remove<TKey, TValue>(
target.TryGetValue(key, out value);
return target.Remove(key);
}

#endif
}
}
34 changes: 32 additions & 2 deletions src/Tests/PolyfillTests_Dictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ partial class PolyfillTests
[Test]
public void IReadOnlyDictionaryAsReadOnly()
{
IDictionary<string, string> dictionary = new Dictionary<string,string>
IDictionary<string, string> dictionary = new Dictionary<string, string>
{
{"key", "value"}
};
Expand All @@ -12,10 +12,40 @@ public void IReadOnlyDictionaryAsReadOnly()
Assert.AreEqual("value", readOnly["key"]);
}

[Test]
public void Dictionary_TryAdd_ThrowsOnNullKey()
{
var dictionary = new Dictionary<string, int>();

Assert.Throws<ArgumentNullException>(() => dictionary.TryAdd(null!, 1));
}

[Test]
public void Dictionary_TryAdd_ReturnsTrueOnSuccessfulAdd()
{
var dictionary = new Dictionary<string, string>();

var entryAdded = dictionary.TryAdd("key", "value");

Assert.True(entryAdded);
Assert.AreEqual("value", dictionary["key"]);
}

[Test]
public void Dictionary_TryAdd_ReturnsFalseIfElementAlreadyPresent()
{
var dictionary = new Dictionary<string, string>() { { "existingKey", "original value" } };

var entryAdded = dictionary.TryAdd("existingKey", "new value");

Assert.False(entryAdded);
Assert.AreEqual("original value", dictionary["existingKey"]);
}

[Test]
public void Dictionary_Remove()
{
var dictionary = new Dictionary<string, string?> { {"key", "value"} };
var dictionary = new Dictionary<string, string?> { { "key", "value" } };

Assert.True(dictionary.Remove("key", out var value));
Assert.AreEqual("value", value);
Expand Down

0 comments on commit 139d797

Please sign in to comment.