diff --git a/DeepClone.Test/SpecializedCollectionTests.cs b/DeepClone.Test/SpecializedCollectionTests.cs index 8659464..a0db437 100644 --- a/DeepClone.Test/SpecializedCollectionTests.cs +++ b/DeepClone.Test/SpecializedCollectionTests.cs @@ -39,6 +39,62 @@ public void HashSet_DeepClone_ShouldCreateIndependentCopy() Assert.AreEqual("Item1", originalItem.Name); } + /// + /// Tests deep cloning an IReadOnlyDictionary. + /// + [TestMethod] + public void ReadOnlyDictionary_DeepClone_ShouldCreateIndependentCopy() + { + // Arrange + Dictionary original = new() + { + ["a"] = new() { Id = 1, Name = "Item1" }, + ["b"] = new() { Id = 2, Name = "Item2" } + }; + + // Act + IReadOnlyDictionary clone = ((IReadOnlyDictionary)original).DeepClone(); + + // Assert + Assert.IsNotNull(clone); + Assert.HasCount(original.Count, clone); + Assert.AreEqual(1, clone["a"].Id); + Assert.AreEqual("Item2", clone["b"].Name); + Assert.AreNotSame(original["a"], clone["a"]); + + // Verify independence + clone["a"].Name = "Modified"; + Assert.AreEqual("Item1", original["a"].Name); + } + + /// + /// Tests deep cloning an empty IReadOnlyDictionary. + /// + [TestMethod] + public void ReadOnlyDictionary_DeepClone_Empty_ShouldReturnEmptyDictionary() + { + // Arrange + Dictionary original = []; + + // Act + IReadOnlyDictionary clone = ((IReadOnlyDictionary)original).DeepClone(); + + // Assert + Assert.IsNotNull(clone); + Assert.IsEmpty(clone); + } + + /// + /// Tests that deep cloning a null IReadOnlyDictionary throws. + /// + [TestMethod] + public void ReadOnlyDictionary_DeepClone_Null_ShouldThrow() + { + IReadOnlyDictionary original = null!; + + Assert.ThrowsExactly(() => original.DeepClone()); + } + /// /// Tests deep cloning a SortedSet. /// diff --git a/DeepClone/DeepCloneContainerExtensions.cs b/DeepClone/DeepCloneContainerExtensions.cs index 6d2b6f8..b69f53f 100644 --- a/DeepClone/DeepCloneContainerExtensions.cs +++ b/DeepClone/DeepCloneContainerExtensions.cs @@ -160,9 +160,16 @@ public static IDictionary DeepClone(this IDictionary /// var clonedReadOnlyDict = originalReadOnlyDict.DeepClone(); /// /// + /// Thrown if source is null. public static IReadOnlyDictionary DeepClone(this IReadOnlyDictionary source) - where TKey : notnull => - (IReadOnlyDictionary)source.ToDictionary(DeepClone, DeepClone); + where TKey : notnull + { + Ensure.NotNull(source); + + return source.ToDictionary( + pair => DeepClone(pair.Key), + pair => DeepClone(pair.Value)); + } /// /// Deep clones a hash set.