Skip to content

Fix IReadOnlyDictionary DeepClone throwing InvalidCastException - #78

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/readonly-dictionary-deepclone-76
Sep 26, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/readonly-dictionary-deepclone-76

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #76

What was wrong

DeepClone(this IReadOnlyDictionary<TKey, TValue>) passed the DeepClone method group to ToDictionary. That bound it to DeepClone<KeyValuePair<TKey, TValue>>, so the method built a dictionary keyed by pairs. The cast back to IReadOnlyDictionary<TKey, TValue> then threw InvalidCastException on every call, including on an empty dictionary.

Change

  • The method now clones each key and each value on its own, the same way the IDictionary overload does.
  • It also adds the Ensure.NotNull(source) guard and documents the ArgumentNullException.

Tests

SpecializedCollectionTests gains three tests:

  • ReadOnlyDictionary_DeepClone_ShouldCreateIndependentCopy checks that values are independent IDeepCloneable copies.
  • ReadOnlyDictionary_DeepClone_Empty_ShouldReturnEmptyDictionary
  • ReadOnlyDictionary_DeepClone_Null_ShouldThrow

I checked the tests against the old code. With the fix reverted, the first two fail with the InvalidCastException from the issue. With the fix in place, the full suite passes, 36 of 36, on net10.0.

Issue #77 also asks to keep the comparer and remove the ambiguity with Dictionary<,>. This PR deliberately leaves that out.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Q8KgDr8CfZLWPQ5o6nZdcV


Generated by Claude Code

The read-only dictionary overload passed the DeepClone method group to
ToDictionary, which bound it to KeyValuePair and built a dictionary keyed
by pairs, so the cast back to IReadOnlyDictionary failed on every call.
Clone keys and values individually, as the IDictionary overload does, and
add the missing null guard.

Fixes #76

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q8KgDr8CfZLWPQ5o6nZdcV
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

IReadOnlyDictionary<TKey,TValue>.DeepClone() always throws InvalidCastException

2 participants