Senior · Design · Mutation review

Review an API returning a mutable List that callers may retain. Propose either a documented transfer of ownership or an immutable snapshot boundary, and discuss allocation, aliasing and synchronization rather than merely rewriting foreach as a for loop.

Think through your answer before opening the explanation.

Coding interviews

Reveal answer and reasoning

An API can return an immutable snapshot or document exclusive mutable ownership, but a read-only interface alone does not necessarily freeze the backing collection. If callers may retain aliases, mutation needs synchronization or copying at a known boundary. Choose based on caller semantics before optimizing away allocations.

Filtering and RemoveAll each take O(n) predicate work. The filtered array requires O(r) result storage, while RemoveAll compacts the owned list in place with constant auxiliary state. Constructing the separate demonstration copy itself costs O(n) storage; do not omit that cost when describing this exact program. A deferred Where query is not yet a snapshot, so source mutation before enumeration changes its result.

Removing by increasing index can skip shifted elements. Concurrent mutation adds another ownership problem that neither a filtered query nor an unsynchronized list solves automatically.

The interview review should identify the original mutation hazard, choose a deliberate ownership policy and show the observable difference between copying and compaction. It should count both required output and any demonstration copies when describing memory. A useful regression suite covers all matches, no matches and adjacent matches, with sequence assertions and alias checks. A senior explanation recognizes that read-only access and immutable state are different guarantees.

This is a debugging and API-design exercise, so the most important improvement is making mutation responsibility clear rather than merely obtaining the expected two numbers once.

What a strong answer covers

  • An API can return an immutable snapshot or document exclusive mutable ownership, but a read-only interface alone does not necessarily freeze the backing collection.
  • Filtering and RemoveAll each take O(n) predicate work.
  • A deferred Where query is not yet a snapshot, so source mutation before enumeration changes its result.

Common pitfall

A deferred Where query is not yet a snapshot, so source mutation before enumeration changes its result. Removing by increasing index can skip shifted elements. Concurrent mutation adds another ownership problem that neither a filtered query nor an unsynchronized list solves automatically.

Follow-up questions

  1. Test all-matching, none-matching and alternating lists. Hint: count the removed items separately from the kept items and verify the original list remains unchanged only for the copy-returning path.
  2. Does returning IReadOnlyList alone guarantee that the underlying list cannot change?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions