Course contentsShow
← C#
Lesson 455 of 1,9084. Functional Programming with LINQFree lesson

Functional Data Validation Pipelines

Create composable validation logic that treats data objects as streams of state to be verified.

In this lesson, you will learn how to treat your data objects as transient streams of state that pass through a sequence of pure validation functions.

The Pipeline Approach

When we perform data validation, we often fall into the trap of nested if statements or complex try-catch blocks. A functional pipeline treats a data object as a "stream" that travels through a series of filters. Instead of checking if data is valid, we transform the data by passing it through functions that either return the object as-is (if valid) or flag it for error handling.

By using LINQ and functional composition, we can chain these checks so that our logic is declarative and readable.

Composing Validators

Imagine a simple User object. We want to ensure it has a valid email and a non-empty name. Rather than writing one monolithic method, we define a collection of predicates or transformation steps:

public record User(string Name, string Email);

// A simple validation step
Func<User, User?> ValidateEmail = u => u.Email.Contains("@") ? u : null;
Func<User, User?> ValidateName = u => !string.IsNullOrEmpty(u.Name) ? u : null;

// The Pipeline
var validators = new[] { ValidateEmail, ValidateName };

var user = new User("Alice", "alice@example.com");

// We treat the user as a sequence and apply the pipeline
var isValid = validators.All(v => v(user) != null);

Why this matters

In this pattern, the data object is never modified; it is simply inspected as it passes through the "stream" of logic. Because these are pure functions, we avoid the overhead of complex state management. This approach integrates perfectly with our previous lessons on Value-Based LINQ, allowing us to run these checks on high-performance structures without unnecessary allocations. By keeping validation as a series of distinct, composable steps, you make your code easier to test, debug, and extend as your business requirements grow.

Key Takeaway: Functional validation pipelines transform messy conditional logic into a linear, composable stream of pure checks that verify state without mutating data.