Syrx.Validation 3.0.0

dotnet add package Syrx.Validation --version 3.0.0
                    
NuGet\Install-Package Syrx.Validation -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Syrx.Validation" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Syrx.Validation" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Syrx.Validation" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Syrx.Validation --version 3.0.0
                    
#r "nuget: Syrx.Validation, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Syrx.Validation@3.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Syrx.Validation&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Syrx.Validation&version=3.0.0
                    
Install as a Cake Tool

Syrx.Validation

Core validation library with precondition checking for .NET applications

NuGet Version NuGet Downloads License: MIT

Overview

Syrx.Validation is a lightweight, high-performance validation library that provides elegant precondition checking for .NET applications. It transforms verbose multi-line validation statements into clean, readable single-line expressions while giving you complete control over exception handling.

Features

  • Fluent Precondition Checking: Convert multi-line if-throw statements into single-line expressions
  • Flexible Exception Handling: Support for custom exception types and factories
  • High Performance: Near-zero overhead when conditions are met
  • Modern .NET: Full support for .NET 8.0+ with nullable reference types
  • Static Analysis Support: Enhanced with DoesNotReturnIf attributes for better compiler analysis
  • Zero Dependencies: No external dependencies required

Installation

Install via NuGet Package Manager:

Install-Package Syrx.Validation

Or via .NET CLI:

dotnet add package Syrx.Validation

Quick Start

using static Syrx.Validation.Contract;

public class UserService
{
    public void CreateUser(string email, int age)
    {
        // Validate parameters with clean, readable syntax
        Throw<ArgumentNullException>(string.IsNullOrWhiteSpace(email), "Email is required");
        Throw<ArgumentOutOfRangeException>(age < 0 || age > 150, "Age must be between 0 and 150");
        
        // Process validated data
        ProcessUser(email, age);
    }
}

API Reference

Contract Class

The Contract class provides static methods for precondition checking:

Basic Validation
// Throw exception if condition is false
Throw<TException>(bool condition, string message);

// Example
Throw<ArgumentNullException>(value == null, "Value cannot be null");
Formatted Messages
// Support for string formatting
Throw<TException>(bool condition, string message, params object[] args);

// Example
Throw<ArgumentException>(value < 0, "Value {0} must be non-negative", value);
Inner Exception Support
// Include inner exceptions
Throw<TException>(bool condition, string message, Exception innerException);
Throw<TException>(bool condition, string message, Exception innerException, params object[] args);

// Example
Throw<InvalidOperationException>(failed, "Operation failed", innerException);
Exception Factory Pattern
// Use factory delegates for complex exception creation
Throw<TException>(bool condition, Func<TException> exceptionFactory);

// Example
Throw<CustomException>(invalid, () => new CustomException("Custom message", additionalData));
Require Aliases
// All Throw methods have Require aliases for readability
Require<ArgumentNullException>(value != null, "Value is required");

Advanced Usage Examples

Method Parameter Validation

using static Syrx.Validation.Contract;

public class OrderService
{
    public decimal CalculateDiscount(decimal orderAmount, string couponCode, DateTime validUntil)
    {
        // Validate all parameters upfront
        Throw<ArgumentOutOfRangeException>(orderAmount <= 0, 
            "Order amount must be positive, got {0}", orderAmount);
        
        Throw<ArgumentException>(string.IsNullOrWhiteSpace(couponCode), 
            "Coupon code cannot be empty");
        
        Throw<ArgumentException>(validUntil < DateTime.Now, 
            "Coupon expired on {0}", validUntil);
        
        return CalculateDiscountInternal(orderAmount, couponCode);
    }
}

Business Rule Validation

public class BankAccount
{
    private decimal _balance;
    
    public void Withdraw(decimal amount)
    {
        Throw<ArgumentOutOfRangeException>(amount <= 0, 
            "Withdrawal amount must be positive");
        
        Throw<InvalidOperationException>(_balance < amount, 
            "Insufficient funds. Balance: {0}, Requested: {1}", _balance, amount);
        
        _balance -= amount;
    }
}

Custom Exception Types

public class BusinessRuleException : Exception
{
    public string RuleCode { get; }
    
    public BusinessRuleException(string ruleCode, string message) : base(message)
    {
        RuleCode = ruleCode;
    }
}

// Usage
Throw<BusinessRuleException>(violatesRule, 
    () => new BusinessRuleException("BR001", "Business rule violation detected"));

Factory Pattern for Complex Scenarios

public void ProcessPayment(PaymentRequest request)
{
    Throw<PaymentException>(request.Amount <= 0, () => 
        new PaymentException(
            "INVALID_AMOUNT", 
            $"Payment amount {request.Amount} is invalid",
            request.TransactionId
        ));
    
    Throw<PaymentException>(string.IsNullOrEmpty(request.MerchantId), () =>
        new PaymentException(
            "MISSING_MERCHANT",
            "Merchant ID is required for payment processing",
            request.TransactionId
        ));
}

Performance Characteristics

  • Zero Overhead: When conditions are true, the method calls have minimal performance impact
  • Efficient Exception Creation: Exception objects are only created when conditions fail
  • Memory Efficient: No allocations for successful validations
  • Compiler Optimizations: Benefits from JIT compiler optimizations in hot paths

Static Analysis Support

The library includes DoesNotReturnIf attributes that provide enhanced static analysis:

[DoesNotReturnIf(false)]
public static void Throw<T>(bool condition, string message) where T : Exception, new()

This enables:

  • Better null-state analysis
  • Improved unreachable code detection
  • Enhanced compiler warnings and suggestions

Thread Safety

All Contract methods are thread-safe as they are static methods with no shared state. Multiple threads can safely call validation methods concurrently.

Migration from Traditional Validation

Before (Traditional Approach)

public void ProcessOrder(Order order, string customerEmail)
{
    if (order == null)
    {
        throw new ArgumentNullException(nameof(order));
    }
    
    if (string.IsNullOrWhiteSpace(customerEmail))
    {
        throw new ArgumentException("Customer email is required", nameof(customerEmail));
    }
    
    if (order.Items == null || order.Items.Count == 0)
    {
        throw new ArgumentException("Order must contain at least one item", nameof(order));
    }
    
    // Process order...
}

After (With Syrx.Validation)

using static Syrx.Validation.Contract;

public void ProcessOrder(Order order, string customerEmail)
{
    Throw<ArgumentNullException>(order == null, nameof(order));
    Throw<ArgumentException>(string.IsNullOrWhiteSpace(customerEmail), "Customer email is required");
    Throw<ArgumentException>(order.Items?.Count == 0, "Order must contain at least one item");
    
    // Process order...
}

Error Handling Best Practices

1. Use Appropriate Exception Types

// For null arguments
Throw<ArgumentNullException>(value == null, nameof(value));

// For invalid ranges
Throw<ArgumentOutOfRangeException>(index < 0 || index >= array.Length, nameof(index));

// For business rule violations
Throw<InvalidOperationException>(account.IsLocked, "Account is locked");

2. Provide Meaningful Messages

// Good: Specific and actionable
Throw<ArgumentException>(age < 18, "Age must be 18 or older, got {0}", age);

// Avoid: Vague messages
Throw<ArgumentException>(age < 18, "Invalid age");

3. Use Exception Factories for Complex Cases

Throw<ValidationException>(hasErrors, () => 
    new ValidationException("Validation failed", GetValidationErrors()));

Framework Support

  • .NET 8.0: Full support with nullable reference types and performance optimizations
  • .NET 9.0: Full support with latest runtime improvements
  • Dependencies: No external dependencies (uses only System libraries)

Contributing

Contributions are welcome! Please read our Contributing Guidelines for details on how to submit pull requests, report issues, and suggest improvements.

License

This project is licensed under the MIT License - see the license.txt file for details.

Changelog

Version 3.0.0

  • BREAKING CHANGE: Removed .NET 6.0 support
  • Added .NET 9.0 support
  • Now targets .NET 8.0 and .NET 9.0

Version 2.0.0

  • Added DoesNotReturnIf attributes for enhanced static analysis
  • Improved nullable reference type support
  • Added Require method aliases for better readability
  • Performance optimizations
  • Enhanced XML documentation

Version 1.1.0

  • Added exception factory delegate support
  • Improved error message formatting
  • Added inner exception support

Version 1.0.0

  • Initial release with core precondition checking functionality
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on Syrx.Validation:

Package Downloads
Syrx.Commanders.Databases

This package hosts the implementation of the Syrx Database Commander which is a wrapper over Dapper's Query and Execute methods.

Syrx.Commanders.Databases.Settings

This package hosts the types used by the Syrx configuration subsystem.

Syrx.Commanders.Databases.Connectors

Hosts the Syrx IDatabaseConnector which is used to establish an IDbConnection to a supported RDBMS. This package also includes a base DatabaseConnector which can be used with any RDBMS that supports creating an IDbConnection through a DbProviderFactory instance.

Syrx.Commanders.Databases.Settings.Extensions.Xml

This package adds support for configuration of Syrx database commands via XML file.

Syrx.Commanders.Databases.Settings.Extensions.Json

This package adds support for configuration of Syrx database commands via JSON file.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 190 10/26/2025
2.0.0 4,844 6/10/2024
1.2.0 756 9/27/2019
1.1.0 1,004 8/25/2018
1.0.0 14,258 10/1/2017

Version 3.0.0: Breaking change - Removed .NET 6.0 support, added .NET 9.0 support. Now targets .NET 8.0 and .NET 9.0.