Skip to content

Commit f2c8cf9

Browse files
committed
Feat: Add AddOrUpdate extension methods for dictionaries with tests
1 parent eced0b3 commit f2c8cf9

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

src/CodeOfChaos.Extensions/DictionaryExtensions.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,32 @@ TValue value
1818
dictionary[key] = value;
1919
return dictionary;
2020
}
21+
22+
public static Dictionary<TKey, TValue> AddOrUpdate<TKey, TValue>(
23+
this Dictionary<TKey, TValue> dictionary,
24+
TKey key,
25+
Func<TKey, TValue> valueFactory
26+
) where TKey : notnull {
27+
if (dictionary.TryAdd(key, valueFactory(key))) return dictionary;
28+
dictionary[key] = valueFactory(key);
29+
return dictionary;
30+
}
31+
32+
public static Dictionary<TKey, TValue> AddOrUpdate<TKey, TValue>(
33+
this Dictionary<TKey, TValue> dictionary,
34+
TKey key,
35+
Func<TKey, TValue> addValueFactory,
36+
Func<TKey, TValue, TValue> updateValueFactory
37+
) where TKey : notnull {
38+
if (dictionary.TryGetValue(key, out TValue? value)) {
39+
value = updateValueFactory(key, value);
40+
dictionary[key] = value;
41+
return dictionary;
42+
}
43+
value = addValueFactory(key);
44+
dictionary.Add(key, value);
45+
return dictionary;
46+
}
2147

2248
public static bool TryAddToOrCreateCollection<TKey, TValue, TCollection>(
2349
this Dictionary<TKey, TCollection> dictionary,

tests/Tests.CodeOfChaos.Extensions/DictionaryExtensionTests.cs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,63 @@ public async Task GetOrAdd_ShouldAddValueToDictionary_WhenKeyDoesNotExist_Overlo
109109
await Assert.That(dictionary.ContainsKey("key1")).IsTrue();
110110
await Assert.That(dictionary["key1"]).IsEqualTo("value10");
111111
}
112+
113+
// ReSharper disable once UnusedParameter.Local
114+
// ReSharper disable once ConvertToLocalFunction
115+
[Test]
116+
public async Task AddOrUpdate_ShouldAddValueToDictionary_WhenKeyDoesNotExist_OverloadFactory() {
117+
// Arrange
118+
var dictionary = new Dictionary<string, string>();
119+
const string value = "value";
120+
Func<string, string> valueFactory = key => value;
121+
122+
// Act
123+
dictionary.AddOrUpdate("key1", valueFactory);
124+
125+
// Assert
126+
await Assert.That(dictionary.ContainsKey("key1")).IsTrue();
127+
await Assert.That(dictionary["key1"]).IsEqualTo(value);
128+
}
129+
130+
// ReSharper disable once UnusedParameter.Local
131+
// ReSharper disable once ConvertToLocalFunction
132+
[Test]
133+
public async Task AddOrUpdate_ShouldAddValueToDictionary_WhenKeyDoesExist_OverloadFactory() {
134+
// Arrange
135+
var dictionary = new Dictionary<string, string> { ["key1"] = "oldValue" };
136+
137+
const string value = "value";
138+
Func<string, string> valueFactory = key => $"{value}";
139+
140+
// Act
141+
dictionary.AddOrUpdate("key1", valueFactory);
142+
143+
// Assert
144+
await Assert.That(dictionary).ContainsKey("key1");
145+
await Assert.That(dictionary["key1"])
146+
.IsNotEqualTo("oldValue")
147+
.IsEqualTo("value");
148+
}
149+
150+
// ReSharper disable once UnusedParameter.Local
151+
// ReSharper disable once ConvertToLocalFunction
152+
[Test]
153+
public async Task AddOrUpdate_ShouldAddValueToDictionary_WhenKeyDoesNotExist_OverloadFactoryAddAndUpdate() {
154+
// Arrange
155+
var dictionary = new Dictionary<string, string> { ["key1"] = "oldValue" };
156+
const string value = "value";
157+
Func<string, string> onAddFactory = key => value;
158+
Func<string, string, string> onUpdateFactory = (_, oldValue) => $"{oldValue};{value}";
159+
160+
// Act
161+
dictionary.AddOrUpdate("key1", onAddFactory, onUpdateFactory);
162+
dictionary.AddOrUpdate("key2", onAddFactory, onUpdateFactory);
163+
164+
// Assert
165+
await Assert.That(dictionary).ContainsKey("key1");
166+
await Assert.That(dictionary["key1"]).IsEqualTo("oldValue;value");
167+
168+
await Assert.That(dictionary).ContainsKey("key2");
169+
await Assert.That(dictionary["key2"]).IsEqualTo(value);
170+
}
112171
}

0 commit comments

Comments
 (0)