Skip to main content

Numeric Methods

This page covers all numeric-related methods available in ValiFlow<T>. They are defined in NumericExpression<TBuilder, T> and ComparisonExpression<TBuilder, T>, and are accessible directly from your ValiFlow<T> builder instance.

Examples: ValiFlow · Evaluators

Unless stated otherwise, each method supports 6 numeric overloads: int, long, float, double, decimal, and short. Examples below use int and decimal for brevity — the same signatures apply for all supported types.


Zero

Zero

Passes when the value equals 0.

var rule = new ValiFlow<Order>()
.Zero(x => x.Quantity);

NotZero

Passes when the value is not equal to 0.

var rule = new ValiFlow<Product>()
.NotZero(x => x.Price);

Sign

Positive

Passes when the value is strictly greater than 0.

var rule = new ValiFlow<Product>()
.Positive(x => x.Amount);

Negative

Passes when the value is strictly less than 0.

var rule = new ValiFlow<Order>()
.Negative(x => x.Balance);

Comparison (value)

GreaterThan

Passes when the property value is strictly greater than the given constant. Supports 6 numeric overloads.

var rule = new ValiFlow<Order>()
.GreaterThan(x => x.Total, 0m);

var rule = new ValiFlow<Product>()
.GreaterThan(x => x.Stock, 0);

GreaterThanOrEqualTo

Passes when the property value is greater than or equal to the given constant.

var rule = new ValiFlow<Order>()
.GreaterThanOrEqualTo(x => x.Quantity, 1);

LessThan

Passes when the property value is strictly less than the given constant.

var rule = new ValiFlow<Product>()
.LessThan(x => x.Price, 1000m);

LessThanOrEqualTo

Passes when the property value is less than or equal to the given constant.

var rule = new ValiFlow<User>()
.LessThanOrEqualTo(x => x.Age, 120);

EqualTo

Passes when the numeric value equals the given constant exactly. This is the numeric-specific equality overload (as opposed to the general == predicate).

var rule = new ValiFlow<Product>()
.EqualTo(x => x.Score, 100);

Cross-field Comparison

These overloads compare two properties of the same entity against each other. They accept any type that implements IComparable<T>, making them suitable for DateTime, decimal, int, and similar types.

GreaterThan (cross-field)

Passes when the first property's value is strictly greater than the second property's value.

var rule = new ValiFlow<Order>()
.GreaterThan(x => x.EndDate, x => x.StartDate);

GreaterThanOrEqualTo (cross-field)

var rule = new ValiFlow<Product>()
.GreaterThanOrEqualTo(x => x.Max, x => x.Min);

LessThan (cross-field)

var rule = new ValiFlow<Product>()
.LessThan(x => x.Price, x => x.Cap);

LessThanOrEqualTo (cross-field)

var rule = new ValiFlow<Order>()
.LessThanOrEqualTo(x => x.Quantity, x => x.Stock);

Range

InRange

Passes when the value falls within the inclusive range [min, max]. Supports 6 numeric overloads and a cross-property variant.

// Constant bounds
var rule = new ValiFlow<Product>()
.InRange(x => x.Score, 0, 100);

// Cross-property bounds
var rule = new ValiFlow<Product>()
.InRange(x => x.Value, x => x.Min, x => x.Max);

Between

Alias / variant of InRange with inclusive semantics. Use when the intent reads more naturally as a range description.

var rule = new ValiFlow<User>()
.Between(x => x.Age, 18, 65);

IsBetweenExclusive

Passes when the value is strictly inside the open interval (min, max) — both bounds are excluded. Supports 6 numeric overloads.

// 0 < Discount < 100
var rule = new ValiFlow<Product>()
.IsBetweenExclusive(x => x.Discount, 0, 100);

Tolerance

IsCloseTo

Passes when |value - target| <= tolerance. Useful for floating-point comparisons. Supports float and double.

var rule = new ValiFlow<Product>()
.IsCloseTo(x => x.Weight, 0.5, 0.01); // within ±0.01 of 0.5

var rule = new ValiFlow<Order>()
.IsCloseTo(x => x.Latitude, 40.7128, 0.001);

Parity

IsEven

Passes when the value is divisible by 2. Supports int and long.

var rule = new ValiFlow<Order>()
.IsEven(x => x.Quantity);

IsOdd

Passes when the value is not divisible by 2. Supports int and long.

var rule = new ValiFlow<Product>()
.IsOdd(x => x.Id);

IsMultipleOf

Passes when the value is an exact multiple of the given divisor. Supports int and long.

var rule = new ValiFlow<Order>()
.IsMultipleOf(x => x.Quantity, 5);

Extremes

MinValue

Passes when the property value equals the minimum representable value for the type (e.g., int.MinValue, decimal.MinValue). Supports 6 numeric overloads.

var rule = new ValiFlow<Product>()
.MinValue(x => x.Priority);

MaxValue

Passes when the property value equals the maximum representable value for the type. Supports 6 numeric overloads.

var rule = new ValiFlow<Product>()
.MaxValue(x => x.Priority);

Nullable Numeric

These methods handle nullable numeric properties (int?, long?, decimal?, double?, float?).

IsNullOrZero

Passes when the nullable value is null or 0.

var rule = new ValiFlow<Product>()
.IsNullOrZero(x => x.Discount);

IsNotNullOrZero

Passes when the nullable value is neither null nor 0.

var rule = new ValiFlow<Product>()
.IsNotNullOrZero(x => x.Price);

Combined Example

The following rule validates a Product entity with a variety of numeric constraints:

var rule = new ValiFlow<Product>()
.NotZero(x => x.Price)
.Positive(x => x.Price)
.InRange(x => x.Stock, 0, 10000)
.IsBetweenExclusive(x => x.Discount, 0, 100) // 0 < Discount < 100
.IsCloseTo(x => x.Weight, 0.5, 0.01); // within ±0.01 of 0.5

bool isValid = rule.Evaluate(product);

// Build the expression for LINQ/EF Core
Expression<Func<Product, bool>> expr = rule.Build();
var availableProducts = dbContext.Products.Where(expr).ToList();

Mini Examples

1) Price range + discount bound

var rule = new ValiFlow<Product>()
.InRange(p => p.Price, 10m, 500m)
.IsBetweenExclusive(p => p.Discount, 0m, 60m);

2) Tolerance for floating values

var rule = new ValiFlow<SensorReading>()
.IsCloseTo(x => x.Temperature, 20.0, 0.25);