Skip to content

Built-in validators

All fifteen validator attributes, with constructor signatures, applicable types and default messages.

4 min read

Every validator lives in Immediate.Validations.Shared and derives from ValidatorAttribute, so all of them accept a Message property to override the default text. “Applies to” is decided by the first parameter of the validator’s ValidateProperty method: applying one to an incompatible property type produces IV0014 and the validator is silently dropped from generation.

ValidatorConstructorApplies toDefault message
EmptyEmpty()any type'{PropertyName}' must be empty.
NotEmptyNotEmpty()any type'{PropertyName}' must not be empty.
NotNullNotNull()any type'{PropertyName}' must not be null.
EqualEqual(object comparison)any type'{PropertyName}' must be equal to '{ComparisonValue}'.
NotEqualNotEqual(object comparison)any type'{PropertyName}' must not be equal to '{ComparisonValue}'.
GreaterThanGreaterThan(object comparison)any type'{PropertyName}' must be greater than '{ComparisonValue}'.
GreaterThanOrEqualGreaterThanOrEqual(object comparison)any type'{PropertyName}' must be greater than or equal to '{ComparisonValue}'.
LessThanLessThan(object comparison)any type'{PropertyName}' must be less than '{ComparisonValue}'.
LessThanOrEqualLessThanOrEqual(object comparison)any type'{PropertyName}' must be less than or equal to '{ComparisonValue}'.
LengthLength(object minLength, object maxLength)string'{PropertyName}' must be between {MinLengthValue} and {MaxLengthValue} characters.
MinLengthMinLength(object minLength)string'{PropertyName}' must be more than {MinLengthValue} characters.
MaxLengthMaxLength(object maxLength)string'{PropertyName}' must be less than {MaxLengthValue} characters.
MatchMatch(object? expr = null, object? regex = null)string'{PropertyName}' is not in the correct format.
EnumValueEnumValue()any enum'{PropertyName}' has a range of values which does not include '{PropertyValue}'.
OneOfOneOf(params object[] values)any type'{PropertyName}' was not one of the specified values: {ValuesValue}.

Validator reference

Empty

Passes when the value is “empty”: null, a string that is null, empty or whitespace, an ICollection with a Count of zero, or any other value equal to default(T) — so 0 for int, default for a struct.

[Validate]
public sealed partial record Query : IValidationTarget<Query>
{
	[Empty]
	public required string? MustBeBlank { get; init; }
}

NotEmpty

The exact negation of Empty. Note that on an int this rejects 0, and on a string it rejects " " as well as "".

[NotEmpty]
public required string Name { get; init; }

Applied to a collection, an untargeted [NotEmpty] requires the collection to be non-empty; [element: NotEmpty] requires each element to be. See Nested and collection validation.

NotNull

Passes when the value is not null.

// only needed on a nullable property — non-nullable ones get this implicitly
[NotNull]
public required string? MustBePresent { get; init; }

Equal

Compares with EqualityComparer<T>.Default.

[Equal(42)]
public required int Answer { get; init; }

public required string Password { get; init; }

[Equal(nameof(Password))]
public required string ConfirmPassword { get; init; }

NotEqual

The negation of Equal, also using EqualityComparer<T>.Default.

[NotEqual(0)]
public required int Delta { get; init; }

GreaterThan

Uses Comparer<T>.Default; passes when the comparison result is greater than zero. Any type with a default comparer works — numbers, DateTime, string (ordinal-ish culture comparison), anything implementing IComparable<T>.

[GreaterThan(0)]
public required int Id { get; init; }

GreaterThanOrEqual

As GreaterThan, but the comparison result may also be zero.

[GreaterThanOrEqual(0)]
public required decimal Balance { get; init; }

LessThan

Uses Comparer<T>.Default; passes when the comparison result is less than zero.

public required int Maximum { get; init; }

[LessThan(nameof(Maximum))]
public required int Minimum { get; init; }

LessThanOrEqual

As LessThan, but the comparison result may also be zero.

[LessThanOrEqual(100)]
public required int Percentage { get; init; }

Length

Strings only. Passes when target.Length is between minLength and maxLength, inclusive at both ends. Both arguments must be int.

[Length(2, 50)]
public required string Name { get; init; }

MinLength

Strings only. Passes when target.Length >= minLength — the bound is inclusive, despite the default message reading “must be more than”.

[MinLength(8)]
public required string Password { get; init; }

MaxLength

Strings only. Passes when target.Length <= maxLength — again inclusive, despite the default message reading “must be less than”.

[MaxLength(50)]
public required string Name { get; init; }

Match

Strings only. Takes either a regex pattern string or a Regex instance. The first positional argument is expr; pass a Regex by name.

// pattern string — compiled on each call with a 1 second match timeout
[Match(@"^d+$")]
public required string DigitsOnly { get; init; }
// a source-generated Regex, referenced by nameof
[GeneratedRegex(@"^d+$")]
private static partial Regex AllDigitsRegex();

[Match(regex: nameof(AllDigitsRegex))]
public required string Id { get; init; }

EnumValue

Enums only (and nullable enums). Passes when Enum.IsDefined returns true. For an enum marked [Flags], a value that is not itself a declared member still passes when every set bit is covered by the union of all declared members.

public enum Status { None = 0, Active, Archived }

[Flags]
public enum Permissions { None = 0, Read = 1, Write = 2 }

[Validate]
public sealed partial record Query : IValidationTarget<Query>
{
	// [EnumValue] is implicit — (Status)42 fails
	public required Status Status { get; init; }

	// Read | Write passes; (Permissions)4 fails
	public required Permissions Permissions { get; init; }
}

OneOf

Passes when the value equals one of the supplied values, compared with the default equality comparer. Accepts a variable number of arguments, or a nameof reference to an array-typed member.

[OneOf("red", "green", "blue")]
public required string Colour { get; init; }
private static readonly string[] s_allowed = ["red", "green", "blue"];

[OneOf(nameof(s_allowed))]
public required string Colour { get; init; }

The values are rendered into {ValuesValue} joined with ", ".