Skip to main content

Static Builder

The Spec static class provides an alternative to the fluent API when you prefer explicit type arguments or are composing specs from two separate variables.

API

public static class Spec
{
public static AndSpecification<TLeft, TRight, T> And<TLeft, TRight, T>(TLeft left, TRight right)
where TLeft : struct, ISpecification<T>
where TRight : struct, ISpecification<T>;

public static OrSpecification<TLeft, TRight, T> Or<TLeft, TRight, T>(TLeft left, TRight right)
where TLeft : struct, ISpecification<T>
where TRight : struct, ISpecification<T>;

public static NotSpecification<TInner, T> Not<TInner, T>(TInner inner)
where TInner : struct, ISpecification<T>;
}

Usage

var spec = Spec.And<ActiveUserSpec, PremiumUserSpec, User>(new(), new(1000m));
var orSpec = Spec.Or<ActiveUserSpec, PremiumUserSpec, User>(new(), new(500m));
var notSpec = Spec.Not<ActiveUserSpec, User>(new());

Fluent vs Static Builder

Both APIs produce the same struct types:

// Fluent
var a = new ActiveUserSpec().And(new PremiumUserSpec(1000m));
// type: AndSpecification<ActiveUserSpec, PremiumUserSpec, User>

// Static builder
var b = Spec.And<ActiveUserSpec, PremiumUserSpec, User>(new(), new(1000m));
// type: AndSpecification<ActiveUserSpec, PremiumUserSpec, User>

Use the static builder when:

  • You need explicit type arguments for disambiguation
  • You are composing two existing spec variables
  • You prefer a functional style over method chaining