Thanks both. This is now implemented and scheduled for the next release: https://feedback.objo.dev/feature/1356
Decimal is a native, non-nullable Objo value type backed by .NET’s 128-bit decimal, rather than a heap-allocated class. It provides 28–29 significant digits with a stored scale of 0–28 fractional digits. That does not reach SQL’s common 38-digit maximum, but comfortably exceeds the 19-digit alternative mentioned above.
Decimal literals use a case-insensitive d suffix:
Var unitPrice As Decimal = 19.95d
Var rate As Decimal = 0.1234567890123456789012345678d
Print((0.1d + 0.2d).ToString()) # 0.3
It supports +, -, *, /, Mod, unary negation, and all comparison operators. Integer operands widen exactly to Decimal. Mixing Decimal and Double requires an explicit conversion so that binary floating-point values cannot silently contaminate an exact calculation.
The API includes:
Parse() and TryParse(), including locale-aware overloads
- Invariant and locale-aware
ToString() formatting
- Exact Currency conversion
- Explicit Double conversion
Abs(), Ceiling(), Floor(), Truncate(), Sign() and Clamp()
- All four
Round() forms, with ties-to-even as the default and RoundingMode.AwayFromZero available
MinValue, MaxValue, Zero, One, MaxScale and the stored Scale
Decimal retains its stored scale, but it is not a SQL-style DECIMAL(p, s) declaration. Silent rounding during assignment would make intermediate calculations harder to reason about, so rounding is explicit at the boundary where it is required:
Var result As Decimal = calculation.Round(6)
Database integration is included. Prepared statements accept Decimal values for SQL Server, PostgreSQL, MySQL and ODBC, while DatabaseColumn.DecimalValue retrieves them. SQLite has no exact decimal storage class, so Objo binds Decimal as invariant text there; a TEXT-affinity column should be used when every source digit must survive.
There is an inherent performance cost compared with Integer or Double arithmetic, but Decimal remains inline inside the VM’s existing 24-byte Value representation and does not allocate a separate object for every value or operation.
For the initial release, Decimal values cannot be Dictionary keys or HashSet items.
Regarding MemoryBlock: I have not added Decimal read/write methods yet. I agree they would be useful, but I do not want to expose the CLR’s internal Decimal layout accidentally as Objo’s permanent binary format. That needs an explicitly specified byte order and stable representation, so I think I will revisit that at a later date if there is sufficient demand.