Skip to content

V0 From{Unit} factories throw ArithmeticException for NaN instead of the documented ArgumentException #326

Description

@matt-edmondson

What's wrong

Vector0Guards.EnsureNonNegative and EnsurePositive (Semantics.Quantities/Vector0Guards.cs around lines 34 and 60) test the value with T.Sign(value). For double, float and Half, Sign(NaN) throws ArithmeticException ("Function does not accept floating point Not-a-Number values."), so the documented ArgumentException is never reached.

Repro

Speed<double>.FromMeterPerSecond(double.NaN), Mass<double>.FromKilogram(double.NaN) and Wavelength<double>.FromMeter(double.NaN) all throw ArithmeticException.

Why it matters

Four places say this should be an ArgumentException:

  • the guard XML docs;
  • every generated factory's XML (for example Speed.g.cs around line 101), which documents only ArgumentException;
  • the Quantities docs;
  • CLAUDE.md ("Throw ArgumentException for validation failures").

A caller that validates user input by catching ArgumentException gets an unhandled ArithmeticException instead. #285's suggested fix routes scalar * and / through these guards, which would spread the same exception to arithmetic results such as 0 * ∞.

Suggested fix

In both guards, check T.IsNaN(value) first and throw ArgumentException($"Magnitude must be a number; received NaN.", paramName). Then compare with value < T.Zero / value <= T.Zero rather than T.Sign.

Acceptance: add tests for both guards with double.NaN, float.NaN and Half.NaN that assert ArgumentException, plus a generated-factory test such as Speed<double>.FromMeterPerSecond(double.NaN).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions