diff --git a/collections-dictionary/UpdateDictionaryValue/Tests/Tests.csproj b/collections-dictionary/UpdateDictionaryValue/Tests/Tests.csproj index 6b815efca5..da8cc3ab2b 100644 --- a/collections-dictionary/UpdateDictionaryValue/Tests/Tests.csproj +++ b/collections-dictionary/UpdateDictionaryValue/Tests/Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net10.0 enable enable @@ -9,10 +9,9 @@ - - - - + + + diff --git a/collections-dictionary/UpdateDictionaryValue/Tests/UpdateDictionaryValueUnitTests.cs b/collections-dictionary/UpdateDictionaryValue/Tests/UpdateDictionaryValueUnitTests.cs index 069334fa67..b245b06592 100644 --- a/collections-dictionary/UpdateDictionaryValue/Tests/UpdateDictionaryValueUnitTests.cs +++ b/collections-dictionary/UpdateDictionaryValue/Tests/UpdateDictionaryValueUnitTests.cs @@ -1,3 +1,4 @@ +using System.Collections.Concurrent; using UpdateDictionaryValue; namespace Tests @@ -35,5 +36,41 @@ public void GivenUpdatingNewToppingValue_ThenNewToppingIsAdded() Assert.AreEqual(12, dictionary.Toppings["mushroom"]); } + + [TestMethod] + public void GivenExistingTopping_WhenAddToppingIfMissing_ThenValueIsUnchanged() + { + var dictionary = new ToppingsDictionary(); + + dictionary.AddToppingIfMissing("pepperoni", 100); + dictionary.AddToppingIfMissing("mushroom", 2); + + Assert.AreEqual(4, dictionary.Toppings["pepperoni"]); + Assert.AreEqual(2, dictionary.Toppings["mushroom"]); + } + + [TestMethod] + public void GivenNewAndExistingToppings_WhenAddToppingsByRef_ThenBothAreUpdated() + { + var dictionary = new ToppingsDictionary(); + + dictionary.AddToppingsByRef("mushroom", 5); + dictionary.AddToppingsByRef("pepperoni", 4); + + Assert.AreEqual(5, dictionary.Toppings["mushroom"]); + Assert.AreEqual(8, dictionary.Toppings["pepperoni"]); + } + + [TestMethod] + public void GivenConcurrentDictionary_WhenAddOrUpdate_ThenAddsThenUpdates() + { + var toppings = new ConcurrentDictionary(); + + var first = toppings.AddOrUpdate("pepperoni", 4, (_, currentAmount) => currentAmount + 4); + var second = toppings.AddOrUpdate("pepperoni", 4, (_, currentAmount) => currentAmount + 4); + + Assert.AreEqual(4, first); + Assert.AreEqual(8, second); + } } } \ No newline at end of file diff --git a/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/Program.cs b/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/Program.cs index 7e8d7144f4..7b2342ea7f 100644 --- a/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/Program.cs +++ b/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/Program.cs @@ -1,20 +1,37 @@ -using UpdateDictionaryValue; +using System.Collections.Concurrent; +using UpdateDictionaryValue; var toppingsDictionary = new ToppingsDictionary(); toppingsDictionary.AddToppings("pepperoni", 4); +toppingsDictionary.AddToppings("olive", 3); + +PrintToppings(toppingsDictionary); try { - toppingsDictionary.Toppings["jalepeno"] = toppingsDictionary.Toppings["jalepeno"] + 1; + // The indexer-only version of AddToppings reads the value before it writes it + toppingsDictionary.Toppings["jalapeno"] = toppingsDictionary.Toppings["jalapeno"] + 1; } -catch (Exception e) +catch (KeyNotFoundException e) { - Console.WriteLine(e); + Console.WriteLine($"{e.GetType()}: {e.Message}"); } -toppingsDictionary.AddToppings("jalepeno", 1); +toppingsDictionary.AddToppings("jalapeno", 1); + +PrintToppings(toppingsDictionary); + +var toppings = new ConcurrentDictionary(); -foreach (var topping in toppingsDictionary.Toppings) +Console.WriteLine(toppings.AddOrUpdate("pepperoni", 4, (_, currentAmount) => currentAmount + 4)); +Console.WriteLine(toppings.AddOrUpdate("pepperoni", 4, (_, currentAmount) => currentAmount + 4)); + +static void PrintToppings(ToppingsDictionary toppingsDictionary) { - Console.WriteLine($"{topping.Key} = {topping.Value}"); -} \ No newline at end of file + foreach (var topping in toppingsDictionary.Toppings) + { + Console.WriteLine($"{topping.Key} = {topping.Value}"); + } + + Console.WriteLine(); +} diff --git a/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/ToppingsDictionary.cs b/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/ToppingsDictionary.cs index 05ab025c0d..d7a8791371 100644 --- a/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/ToppingsDictionary.cs +++ b/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/ToppingsDictionary.cs @@ -1,8 +1,10 @@ -namespace UpdateDictionaryValue +using System.Runtime.InteropServices; + +namespace UpdateDictionaryValue { public class ToppingsDictionary { - public Dictionary Toppings { get; private set; } + public Dictionary Toppings { get; } public ToppingsDictionary() { @@ -25,5 +27,21 @@ public void AddToppings(string toppingType, int amount) Toppings.Add(toppingType, amount); } } + + public void AddToppingIfMissing(string toppingType, int amount) + { + if (!Toppings.TryAdd(toppingType, amount)) + { + Console.WriteLine($"{toppingType} is already on the pizza."); + } + } + + public void AddToppingsByRef(string toppingType, int amount) + { + ref var currentAmount = ref CollectionsMarshal + .GetValueRefOrAddDefault(Toppings, toppingType, out _); + + currentAmount += amount; + } } } diff --git a/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/UpdateDictionaryValue.csproj b/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/UpdateDictionaryValue.csproj index f02677bf64..dfb40caafc 100644 --- a/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/UpdateDictionaryValue.csproj +++ b/collections-dictionary/UpdateDictionaryValue/UpdateDictionaryValue/UpdateDictionaryValue.csproj @@ -2,7 +2,7 @@ Exe - net7.0 + net10.0 enable enable