This lab note is intentionally incomplete.
Question
Can a small enum specification be enough source material to generate a richer, safer enumeration type without forcing every call site to carry the boilerplate?
The current experiment lives in Ifx.Generators. The concrete usage is IsRecoverableErrorSpecification, which marks a small internal enum with GenerateEnumeration("IsRecoverableError").
[GenerateEnumeration("IsRecoverableError")]
internal enum IsRecoverableErrorSpecification
{
No,
Yes
}
That input is deliberately plain. The experiment is about whether the generator can preserve that plainness while producing a type that is better suited for domain code.
Setup
Draft notes:
- Explain the difference between a plain C# enum and the generated enumeration class.
- Describe why
IsRecoverableErroris a useful first example: it is small, binary, and meaningful in error-handling code. - Keep the generator discussion focused on behavior, not Roslyn internals for their own sake.
- Show the generator contract through the attribute: class name, optional default name, namespace, and enumeration base type.
Observation
Draft notes:
- The generator reads enum members and emits a sealed class with static readonly instances.
- It creates an
Allcollection for enumeration and lookup. - It creates
FromValueandFromNamehelpers that fall back to a default value. - The first enum member becomes the default unless another default is supplied.
- The generated type has equality behavior based on the underlying identifier.
The useful pressure is visible immediately: a tiny source declaration produces a more expressive type, but it also hides generated behavior behind convention. That tradeoff needs to be worth it.
Interpretation
Draft notes:
- This is not about avoiding a few lines of code. It is about keeping repeated domain patterns consistent.
- A generator is justified when the boilerplate encodes a rule that should not drift across hand-written implementations.
- The risk is that generated code can make a simple concept feel more magical than it is.
- The design should make the input obvious, the output predictable, and the failure modes easy to inspect.
Next Experiment
Draft notes:
- Decide whether generated lookup should return a default value or expose failure explicitly.
- Add tests that verify generated output for default selection, member values,
FromName,FromValue, and equality. - Consider whether the generated type should support case-insensitive name matching.
- Verify the attribute defaults after the namespace cleanup is complete.
- Decide whether this pattern belongs only in Ifx or should be documented as a broader coding convention.
Lessons So Far
Draft notes:
- Source generators are most useful when they remove repetition from a pattern that already has clear rules.
- The input should stay boring.
- The generated output should be easy to reason about without opening the generator every time.
- Code generation is a design commitment, not just a convenience.