Skip to content

Make the README inheritance sample compile and stay generic down the hierarchy [patch] - #122

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/104-readme-inheritance-example
Nov 4, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/104-readme-inheritance-example

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #104

What changed

The "Inheritance and Deep Cloning" sample in README.md derived ColoredCircle from the concrete Circle : Shape<Circle>. That closes TDerived at Circle, which causes three problems:

  • ColoredCircle.DeepClone(ColoredCircle) failed to compile with CS0115.
  • original.DeepClone() returned Circle, so clone.Color failed to compile.
  • The README's claim that "no casting is needed" was false for that shape of hierarchy.

I took the first option the issue offered:

  • Circle<T> : Shape<T> is now generic and abstract.
  • Circle : Circle<Circle> and ColoredCircle : Circle<ColoredCircle> close the parameter only at the leaves. This is the same pattern as the README's Animal<T>/Mammal<T>/Dog example and Mocks/BaseObject.cs.
  • The usage sample declares ColoredCircle clone = original.DeepClone();, which shows the clone keeps the leaf type.
  • A new paragraph says what goes wrong when a subclass derives from a class that has already closed the parameter. It covers the CS0115 error, the cast at the call site, and the trap where the clone silently becomes a base-class instance when CreateInstance() isn't overridden, plus the covariant-return limit on runtimes before .NET 5.

Tests

ReadmeInheritanceExampleTests:

  • Mirrors the README hierarchy. It clones a ColoredCircle and a Circle, then checks every level's properties and that the collections are independent.
  • Readme_DeclaresTheTestedHierarchy and Readme_DoesNotDeriveFromAClosedCrtpClass read README.md and check it declares the hierarchy the test compiles, so the sample and the test can't drift apart. On main, 5 of these cases fail. With this change they pass. I checked that by stashing the README change and running them again.

Full suite: 74/74 passing on net10.0.


Generated by Claude Code

…hierarchy [patch]

The three-level sample derived ColoredCircle from the concrete Circle,
so its DeepClone(ColoredCircle) override failed with CS0115 and
DeepClone() returned Circle. Keep the intermediate class generic and
abstract, close the CRTP parameter only at the leaves, and say what
goes wrong when a subclass derives from a class that already closed it.
Tests mirror the sample and check README still declares it.

Fixes #104

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

sonarqubecloud Bot commented Nov 2, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit b10d274 into main Nov 4, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/104-readme-inheritance-example branch November 4, 2026 00:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants