Skip to content

Self-owned source (c): subscription to elements of a self-populated collection field #229

Description

@PhysShell

Split from #221 (part c of three). Parent issue has the full sweep context.

The pattern

A constructor (or a method it directly calls) populates a collection field from the class's own factory, then subscribes to each element in a loop. The elements are owned by the class via its own collection — co-lifetimed, a collectable cycle, not a leak.

public ListsAndGridsViewModel() {
    Items1 = CreateData();                                            // own factory fills the field
    foreach (var model in Items1)
        model.PropertyChanged += (s, a) => OnPropertyChanged(...);    // <- flagged today
}

Evidence: MaterialDesignInXamlToolkit src/MainDemo.Wpf/Domain/ListsAndGridsViewModel.cs:16-17 (both demo-app variants).

Design guardrails (fixed at split time)

  • The loop variable must be provably drawn from a field of this (foreach (var x in FieldOrProperty) where the member is this-owned), and that member must be assigned in the same class from a constructor/factory call or collection initializer — not a ctor parameter, not an injected/service-located value. Injected collections keep today's warning (unknown element lifetime).
  • Same-method scope for the loop; the field-population evidence may live in the same ctor or another member of the same class (class-level scan, same mechanism the field-based -= search already uses).
  • Negative control: foreach over a collection parameter (or a field assigned from a ctor parameter) + += on elements → still flagged.

Acceptance

  • Sample with the self-populated-collection shape (silent) + the injected-collection negative control (flagged), CI assertions both ways.
  • Standard gates (run_tests.py, ruff, mypy; extractor half via CI).

Refs: docs/notes/oracle-sweep-2026-07-10.md, docs/notes/field-notes-patterns.md entry 15.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions