Arithmetic and operators
editBuilt-in arithmetic
Built-in arithmetic on numbers keeps the tag, including on the numbers of the framework such as Int128, Half, and BigInteger. So orderNumber + 1 == projectNumber is still reported:
_ = orderNumber + 1 == projectNumber; // MFTV0001, orderNumber + 1 is still an OrderNumber
_ = orderNumber + projectNumber; // MFTV0003
var doubled = meters * 2; // still in Meters
_ = doubled == seconds; // MFTV0001
var speed = meters / seconds; // not tagged
_ = speed == seconds; // ok| Operation | Tag of the result |
|---|---|
+ and - | The tag of their operands. Adding values with different tags is reported (MFTV0003). |
* and / | The tag of the tagged operand when the other operand is not tagged: price * 2 is a price, but meters / seconds is not tagged. |
Unary + and -, ++, --, +=, -= | The tag of the operand. |
%, bitwise operators, shifts, string concatenations | Not tagged: they create another kind of value. |
User-defined operators and conversions
A user-defined operator or conversion creates a new value, so it does not keep the tag of its operands: dueDate - startDate is a TimeSpan, not a due date. Tag the return value of the operator to tag its result, and its parameters to check its operands:
[return: ValueTag("Meters")]
public static Distance operator +([ValueTag("Meters")] Distance left, [ValueTag("Meters")] Distance right) => new(left.Value + right.Value);The parameters of an operator check the operands of a comparison operator, the operand of a unary operator such as -, the target of ++, --, and of a compound assignment such as +=, and the operand of a conversion such as (int)meters, like any other argument. The tagged result of ++, --, and of a compound assignment also flows back to its target, so it must have the tag of the target. Untagged parameters, such as the parameters of the operators of the framework, are not reported in strict mode.