From 7829610cad52ded62fe0fb970889979017df18a3 Mon Sep 17 00:00:00 2001 From: gramps Date: Fri, 30 Oct 2026 15:24:33 -0700 Subject: [PATCH] docs(mistakes): record the record-struct zero-init trap Two controls looked dead because new ScoreboardStyle() zero-initialised instead of applying the declaration's defaults. Recorded with the rule (explicit parameterless ctor) and the testing lesson (a defaults test must construct with new(), not with explicit arguments). --- MyMistakes.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MyMistakes.md b/MyMistakes.md index 2e80880..21e7e55 100644 --- a/MyMistakes.md +++ b/MyMistakes.md @@ -1,3 +1,23 @@ + +## 2026-10-30 — C# record struct: `new T()` ignores the parameter defaults + +**Symptom:** two property controls "had no code behind them" — the Background checkbox and the +opacity slider changed nothing visible. + +**Cause:** `public readonly record struct ScoreboardStyle(string TextColor = "#FFFFFF", bool BackgroundEnabled = true, …)`. +`new ScoreboardStyle()` binds to the implicit **parameterless constructor**, which zero-initialises — +the defaults in the parameter list are only used when the constructor is called with those arguments +omitted *at a call site that supplies some of them*. Result: null colour, `BackgroundEnabled = false`, +`FontOpacity = 0`, `FontSize = 0`. The renderer drew the zeros faithfully, so the UI looked dead +while every unit test of the renderer passed (they constructed the style explicitly). + +**Rule:** a record struct with meaningful defaults needs an explicit parameterless constructor +(`public T() : this() { }`). And a "defaults" test must construct the type the same way +production does — with `new()` — never with explicit arguments, or it proves nothing. + +**Guard:** `ScoreboardRendererTests` asserts `new ScoreboardStyle()` yields white / on / black / 0.20 / +max 200. + # MyMistakes.md > **Two jobs**, distinguished by heading: