---
title: Enforce a method precondition
summary: Fail fast on invalid arguments or state.
status: draft
owner: saif-docgen
last_reviewed: 2026-09-15
library: SAIF.Framework.Common
reference_type: package
operation_id: OP-017
trigger: Called at the top of a public method by consumers and by intra-library callers (`IEnumerableExtensions`, `DictionaryExtensions`, `UriExtensions`)
---

# Enforce a method precondition

Fail fast on invalid arguments or state, triggered when called at the top of a public method by consumers and by intra-library callers (`IEnumerableExtensions`, `DictionaryExtensions`, `UriExtensions`).

| Field | Value |
| --- | --- |
| **Operation ID** | OP-017 |
| **Trigger** | Called at the top of a public method by consumers and by intra-library callers (`IEnumerableExtensions`, `DictionaryExtensions`, `UriExtensions`) |
| **Inputs** | The parameter value, the parameter name, or a boolean / `Func<bool>` condition |
| **Outputs** | The validated value (fluent) or `void`; throws on violation |
| **Primary components** | ``SAIF.Enforce` — `ArgumentNotNull<T>`, `ArgumentNotNullOrEmpty`, `ArgumentNotNullOrWhiteSpace`, `NotNull<T>`, `True` (4 overloads)` |
| **Entry point** | `Common/SAIF.Common/Classes/Enforce.cs` |

## Steps

1. `ArgumentNotNull` first validates its own `parameterName` argument: if null or whitespace, throw `ArgumentNullException("parameterName")`. ([BR-038](../business-rules.md#br-038-a-guard-call-must-itself-supply-a-non-blank-parameter-name))
2. If the parameter itself is null (via `GenericExtensions.IsNull`), throw `ArgumentNullException(parameterName)`; otherwise return the parameter so the call can be chained. ([BR-039](../business-rules.md#br-039-a-guarded-argument-must-not-be-null))
3. `ArgumentNotNullOrEmpty` runs steps 1-2 first, then throws `ArgumentException("Parameter ({name}) cannot be null or empty.")` when the string is empty. ([BR-039](../business-rules.md#br-039-a-guarded-argument-must-not-be-null), [BR-040](../business-rules.md#br-040-a-guarded-string-argument-must-not-be-empty))
4. `ArgumentNotNullOrWhiteSpace` runs steps 1-2 first, then throws `ArgumentException("Parameter ({name}) cannot be null or white space.")` when the string trims to nothing. ([BR-039](../business-rules.md#br-039-a-guarded-argument-must-not-be-null), [BR-041](../business-rules.md#br-041-a-guarded-string-argument-must-not-be-all-white-space))
5. `NotNull<T>` delegates to `GenericExtensions.IfNullThrow<T, InvalidOperationException>` with the message "The type {FullName} cannot be null." — used for state, not arguments. ([BR-042](<../business-rules.md#br-042-a-guarded-state-value-(as-opposed-to-an-argument)-must-not-be-null>))
6. `True<T>(bool)` / `True<T>(Func<bool>)` throw a new parameterless `T : Exception` when the condition is false; `True(bool, Exception)` / `True(Func<bool>, Exception)` throw the caller-supplied exception instance. ([BR-043](../business-rules.md#br-043-a-caller-supplied-boolean-or-func%3Cbool%3E-condition-must-evaluate-true%2C-or-the-caller-specified-exception-type%2Finstance-is-thrown))

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start(["Guard called at top<br>of a method"]) --> P1["ArgumentNotNull validates<br>parameterName"]
	P1 --> C1{"parameterName null<br>or whitespace?"}
	C1 -->|Yes| ErrName(["Throw ArgumentNullException<br>for parameterName"])
	C1 -->|No| P2["Check parameter<br>via IsNull"]
	P2 --> C2{"Parameter is null?"}
	C2 -->|Yes| ErrParam(["Throw ArgumentNullException<br>for parameterName"])
	C2 -->|No| P3["Return parameter<br>for chaining"]
	P3 --> C3{"Called via<br>ArgumentNotNullOrEmpty?"}
	C3 -->|Yes, string empty| ErrEmpty["Throw ArgumentException<br>cannot be null or empty"]
	C3 -->|No| C4{"Called via ArgumentNotNull<br>OrWhiteSpace?"}
	C4 -->|Yes, trims to nothing| ErrWhite["Throw ArgumentException<br>cannot be null or white space"]
	C4 -->|No| C5{"Called via NotNull<T>?"}
	C5 -->|Yes, state is null| ErrState["Delegate to IfNullThrow<br>throw InvalidOperationException"]
	C5 -->|No| C6{"Called via True variant?"}
	C6 -->|Condition false| ErrTrue["Throw parameterless T<br>or caller-supplied exception"]
	C6 -->|Condition true| End(["Guard passes"])
```

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `Common/SAIF.Common/Classes/Enforce.cs`
