Skip to content

DeepCloneFrom empties the destination when dest and source are the same collection instance #64

Closed

Description

@matt-edmondson

What's wrong

In DeepClone/DeepCloneContainerExtensions.cs, both DeepCloneFrom<T>(this ICollection<T> dest, IEnumerable<T> source) and DeepCloneFrom<TKey,TValue>(this IDictionary<TKey,TValue> dest, IDictionary<TKey,TValue> source) do:

dest.Clear();
foreach (var item in source)
{
    dest.Add(...);
}

If dest and source are the same collection instance, Clear() wipes it, and the foreach then enumerates the now-empty source — no InvalidOperationException is thrown, because the enumerator is obtained after the clear. The collection ends up permanently empty.

Why it matters / concrete failure scenario

The method exists specifically for in-place cloning — detaching a collection's elements from a shared object graph without swapping out the collection instance itself, e.g. widget.Parts.DeepCloneFrom(widget.Parts) to deep-clone a list's own contents in place. That exact natural usage — passing a collection's own reference as both dest and source — is the one input that silently destroys all the data instead of cloning it.

Suggested fix

Snapshot source before clearing dest, e.g.:

T[] items = source.ToArray();
dest.Clear();
foreach (var item in items) { dest.Add(...); }

(or the dictionary equivalent), so the clear can't invalidate the enumeration source. Alternatively, explicitly guard against ReferenceEquals(dest, source).

Acceptance criteria

  • A test calling collection.DeepCloneFrom(collection) (same reference for both arguments) results in collection containing clones of its original elements, not an empty collection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions