Skip to content

DeepCopy: dependency-free reflection-based deep clone (11.0.0)#6

Merged
PFalkowski merged 2 commits into
masterfrom
feature/reflection-deepcopy
Jun 13, 2026
Merged

DeepCopy: dependency-free reflection-based deep clone (11.0.0)#6
PFalkowski merged 2 commits into
masterfrom
feature/reflection-deepcopy

Conversation

@PFalkowski

Copy link
Copy Markdown
Owner

Replaces the Newtonsoft JSON round-trip in DeepCopy with a true reflection-based deep clone, and removes the Newtonsoft.Json dependency entirely (it was the only consumer). StandardInterfaces is now the package's only dependency.

Why

The old DeepCopy serialized to JSON and back: it pulled in a heavy dependency, was slow, only copied public properties, required JSON-friendly types, and broke on reference cycles.

New behavior

  • Recursively clones all instance fields, including private and inherited ones.
  • Preserves shared-reference identity (one object referenced by two fields stays a single object in the copy) and handles reference cycles via a reference-equality visited map.
  • No serializable / parameterless-ctor requirement (GetUninitializedObject).
  • Strings and known immutable framework types are reused; delegates and Type are copied by reference; pointer fields are skipped; arrays (including multi-dimensional) are deep-cloned.
  • FieldInfo cached per type; RuntimeHelpers.GetUninitializedObject on net8, FormatterServices on netstandard2.0.

Breaking change → 11.0.0

  • DeepCopy<T>(this T, JsonSerializerSettings) overload is removed; the new signature is DeepCopy<T>(this T).

Tests

Added coverage for nested/collection cloning, private fields, shared-reference identity, reference cycles, and arrays. 182/182 passing, clean build (0 warnings) on both TFMs. Verified the packed nuspec lists only StandardInterfaces.

🤖 Generated with Claude Code

PFalkowski and others added 2 commits June 13, 2026 20:43
Replace the Newtonsoft JSON round-trip with a recursive reflection clone:
- copies all instance fields, including private and inherited ones
- preserves shared-reference identity and handles reference cycles via a
  reference-equality visited map
- no serializable/parameterless-ctor requirement
- strings/known immutables reused; delegates and Type copied by reference;
  pointer fields skipped; arrays (incl. multi-dimensional) deep-cloned
- FieldInfo cached per type; GetUninitializedObject via RuntimeHelpers on
  net8 and FormatterServices on netstandard2.0

Removes the Newtonsoft.Json package dependency and the JsonSerializerSettings
overload (breaking -> 11.0.0). StandardInterfaces is now the only dependency.
Added tests for nested/collection cloning, private fields, shared references,
cycles, and arrays. 182/182 passing, clean build on both TFMs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cover value types/immutables, nullables, inherited private fields,
struct-with-reference, delegate-by-reference, primitive/empty/multi-
dimensional/jagged arrays, Dictionary, self-cycles, and shared-reference
identity within a collection. 195/195 passing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@PFalkowski PFalkowski merged commit b8afcd7 into master Jun 13, 2026
1 check passed
@PFalkowski PFalkowski deleted the feature/reflection-deepcopy branch June 13, 2026 18:57
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.

1 participant