Skip to content

Migrate Digit, Divide, and ExceptNulls off Option#30

Merged
KaliCZ merged 2 commits intomainfrom
claude/condescending-dubinsky-4879ce
Apr 17, 2026
Merged

Migrate Digit, Divide, and ExceptNulls off Option#30
KaliCZ merged 2 commits intomainfrom
claude/condescending-dubinsky-4879ce

Conversation

@KaliCZ
Copy link
Copy Markdown
Owner

@KaliCZ KaliCZ commented Apr 17, 2026

Summary

  • Digit now follows the TryCreate / Create pattern (no Option), lives under src/StrongTypes/Digits/, and implements IEquatable + IComparable against itself, byte, and int.
  • Divide returns decimal?; SafeDivide is a thin Divide(b) ?? otherwise wrapper. Both live in the new src/StrongTypes/Numbers/NumberExtensions.cs.
  • ExceptNulls is reintroduced as an NRT-aware extension in src/StrongTypes/Collections/IEnumerableExtensions.cs (where T : struct on IEnumerable<T?> and where T : class on IEnumerable<T?>). FilterDigits now uses it in place of Flatten(Option<T>).
  • Legacy Digit_Old, DigitExtensions_Old, NumberExtensions_Old and their _Old tests are retired; the duplicate ExceptNulls is removed from the legacy IEnumerableExtensions_Generic_Old partial.

On record struct

I kept Digit as a plain readonly struct. A record struct would auto-generate Equals(Digit) / GetHashCode / == / !=, but we still need to hand-write IEquatable<byte>, IEquatable<int>, all three IComparable<T> overloads, the ordering operators, and a custom ToString() (the synthesized record ToString prints Digit { Value = 5 }). Once you add all that, the savings are small, and the remaining surface reads more uniformly against the other strong types (NonEmptyString, the numeric wrappers) when it's a regular struct with explicit equality.

Test plan

  • dotnet build clean (0 warnings, 0 errors)
  • dotnet test src/StrongTypes.Tests/StrongTypes.Tests.csproj — 470 passed
  • Integration-test suite not run locally (requires Docker/Testcontainers)

Ports Digit and the numeric Divide/SafeDivide extensions away from the
legacy Option<T> surface onto the TryCreate/nullable-return pattern, and
introduces a nullable-reference-types-aware ExceptNulls so FilterDigits
no longer has to flatten Options.

- Digit now uses TryCreate/Create, implements IEquatable and IComparable
  against itself, byte, and int, and lives under src/StrongTypes/Digits.
- Divide returns decimal? and SafeDivide delegates via `Divide ?? otherwise`.
- ExceptNulls moves into src/StrongTypes/Collections with nullable T
  constraints for both struct and class; FilterDigits now uses it.
- Legacy _Old sources and their tests are retired.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@KaliCZ KaliCZ self-assigned this Apr 17, 2026
Adds ==, !=, <, <=, >, >= between Digit and both byte and int, in each
direction, so callers can write `digit == 5` or `(byte)3 < digit` without
routing through the implicit conversions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@KaliCZ KaliCZ enabled auto-merge (squash) April 17, 2026 13:25
@KaliCZ KaliCZ merged commit 13df374 into main Apr 17, 2026
2 checks passed
@KaliCZ KaliCZ deleted the claude/condescending-dubinsky-4879ce branch April 17, 2026 13:25
KaliCZ added a commit that referenced this pull request Apr 19, 2026
* Migrate Digit, Divide, and ExceptNulls off Option

Ports Digit and the numeric Divide/SafeDivide extensions away from the
legacy Option<T> surface onto the TryCreate/nullable-return pattern, and
introduces a nullable-reference-types-aware ExceptNulls so FilterDigits
no longer has to flatten Options.

- Digit now uses TryCreate/Create, implements IEquatable and IComparable
  against itself, byte, and int, and lives under src/StrongTypes/Digits.
- Divide returns decimal? and SafeDivide delegates via `Divide ?? otherwise`.
- ExceptNulls moves into src/StrongTypes/Collections with nullable T
  constraints for both struct and class; FilterDigits now uses it.
- Legacy _Old sources and their tests are retired.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add Digit cross-type operators for byte and int

Adds ==, !=, <, <=, >, >= between Digit and both byte and int, in each
direction, so callers can write `digit == 5` or `(byte)3 < digit` without
routing through the implicit conversions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant