Files
learning-hour-maker/ideas/slice-with-lambda/exercise/csharp/README.md
T
Your Name 77ae05c28c Rename split-loop-with-lambda to slice-with-lambda
The refactoring is now published as Slice on sammancoaching.org:
https://sammancoaching.org/refactorings/slice.html

- git mv ideas/split-loop-with-lambda -> ideas/slice-with-lambda
- rename learning-hour file and update frontmatter name
- update paths in tools/rehearse scripts and report title
- update prose: 'Split Loop with Lambda' -> 'Slice with Lambda'
  in learning hour, exercise READMEs, storyboard, solution comments
- link the published Slice refactoring from the pattern draft
2026-09-29 15:47:30 +00:00

2.3 KiB

Slice with Lambda — C# demo examples

Three C# demo examples for the Slice with Lambda refactoring. Condensed mechanics: https://www.sammancoaching.org/refactorings/slice.html (where that page says mock, we use a lambda instead). Full Java walkthrough: ../../storyboard/storyboard.md. Slides: ~/qwan/slides-rjs/decks/refactoring/slice-with-lambda/slides.md, served at http://localhost:9001/#/refactoring/slice-with-lambda.

The three examples

file guard (client state) unwanted dependency lambda tail
MetaphorFree.cs if (a < 0) return 0; _someDependency.mightThrowWhenPreconditionNotSatisfied(a) Func<int, int> readB = a => ... int c = a + b; return c * 2;
WeatherStation.cs if (_wateredToday) _lightSensor.Read() (byte) Func<byte> readLight = () => ... sunny -> WateringDuration.Medium, shady -> Short (reading > 128 => SunExposure.Sunny)
IceCreamShop.cs if (_thawedToday) _thermometer.Read() (byte) Func<byte> readTemperature = () => ... warm -> ThawAmount.Medium, cold -> Low (temperature > 25 => Warmth.Warm)

In all three, the guard reads client state (a parameter or a flag the client owns), so it stays in the extracted method. Only the dependency call moves into the lambda.

The ramp

MetaphorFree.cs is the smallest possible shape: no loop, one dependency call, a tail of one arithmetic step. It carries the capture-to-parameter lesson: the lambda takes a as its parameter (readB(a)) because a lambda moved up into the function head cannot capture method parameters. Its step-4 stub tests include a throwing stub.

WeatherStation.cs and IceCreamShop.cs are same-shape domain repetitions — guard, one dependency call, map to enum, constant tail — so participants can practice extracting the lambda twice. The C# delegate syntax (Func<byte>) is worth the repetition.

Same three regions every time

Each example deliberately has the same three regions:

  • before: guard clauses
  • middle: one dependency call
  • after: tail that depends on the value the dependency produced

Matching the pattern: extract the dependency-using code into a lambda, slide the definition to the top, extract the method below it, pass the lambda as parameter, test with pure lambda stubs.