### Character and GUID Checks Examples Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Demonstrates validation for GUIDs, substrings, and character properties. ```csharp var guid = guid.MustNotBeEmpty(); var substring = substring.MustBeSubstringOf(text, StringComparisonType.OrdinalIgnoreCase); ``` -------------------------------- ### URI Checks Examples Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Shows examples of validating URIs, URLs, email addresses, and file extensions. ```csharp var endpoint = endpoint.MustBeHttpsUrl(); var email = email.MustBeEmailAddress(); var extension = extension.MustBeFileExtension(new[] { ".jpg", ".png" }); ``` -------------------------------- ### Example usage of IsEmpty GUID check Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Demonstrates how to use the IsEmpty method to check if a GUID is empty and return a specific message if it is. ```csharp if (id.IsEmpty()) { return "No ID provided"; } ``` -------------------------------- ### Install Light.GuardClauses via Visual Studio Package Manager Console Source: https://github.com/feo2x/light.guardclauses/wiki/Home Use this command in the Package Manager Console within Visual Studio to install the Light.GuardClauses NuGet package. ```powershell Install-Package Light.GuardClauses ``` -------------------------------- ### MustStartWith Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/string-checks.md Ensures that the string starts with the specified prefix. This method validates that the input string begins with a given prefix string. ```APIDOC ## MustStartWith ### Description Ensures that the string starts with the specified prefix. ### Method Signature ```csharp public static string MustStartWith(string? parameter, string prefix, string? parameterName = null, string? message = null) ``` ### Parameters #### Path Parameters - **parameter** (string?) - Required - The string to be checked - **prefix** (string) - Required - The required prefix - **parameterName** (string?) - Optional - The name of the parameter - **message** (string?) - Optional - Custom exception message ### Returns string — The validated string ### Throws - `StringDoesNotStartException` — When string does not start with prefix - `ArgumentNullException` — When parameter is null ### Example ```csharp public void SetUrl(string? url) { var validUrl = url.MustStartWith("https://"); _config.Url = validUrl; } ``` ``` -------------------------------- ### Comparison Checks Examples Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Demonstrates usage of comparison-based guard clauses for validating numeric and comparable types. ```csharp var rating = rating.MustBeIn(Range.InclusiveBetween(0, 5)); var distance = distance.MustBeApproximately(expected, tolerance: 0.1); var count = count.MustBeGreaterThan(0).MustBeLessThan(1000); ``` -------------------------------- ### Create Range Description Text Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/types.md Demonstrates how to generate a human-readable description of a range, specifying the connection word between boundaries. ```csharp var range = new Range(0, 100, true, false); var desc = range.CreateRangeDescriptionText(); // "0 (inclusive) to 100 (exclusive)" ``` -------------------------------- ### Install Light.GuardClauses via .NET CLI Source: https://github.com/feo2x/light.guardclauses/wiki/Home Use this command to add the Light.GuardClauses NuGet package to your project using the .NET Command Line Interface. ```bash dotnet add package Light.GuardClauses ``` -------------------------------- ### MustNotStartWith Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/string-checks.md Ensures that the string does not start with the specified prefix. Throws StringStartsWithException if the string starts with the prefix, or ArgumentNullException if the parameter is null. ```APIDOC ## MustNotStartWith ### Description Ensures that the string does not start with the specified prefix. ### Method Signature ```csharp public static string MustNotStartWith(string? parameter, string prefix, string? parameterName = null, string? message = null) ``` ### Parameters #### Path Parameters - **parameter** (string?) - Required - The string to be checked - **prefix** (string) - Required - The forbidden prefix - **parameterName** (string?) - Optional - The name of the parameter - **message** (string?) - Optional - Custom exception message ### Returns string - The validated string ### Throws - `StringStartsWithException` - When string starts with prefix - `ArgumentNullException` - When parameter is null ``` -------------------------------- ### Domain Exception Example with Custom Exceptions Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Illustrates throwing domain-specific exceptions like OrderNotFoundException, PriceRequiredException, and InvalidPriceException. ```csharp public class OrderService { public Order GetOrder(int? orderId) { var validId = orderId.MustHaveValue(() => new OrderNotFoundException("Order ID must be specified")); return _repository.FindById(validId); } public void SetPrice(decimal? price) { var validPrice = price .MustHaveValue(() => new PriceRequiredException()) .MustBeGreaterThan(0, () => new InvalidPriceException("Price cannot be zero or negative")) .MustBeLessThan(decimal.MaxValue / 2, () => new InvalidPriceException("Price exceeds maximum allowed value")); } } public class OrderNotFoundException : Exception { public OrderNotFoundException(string message) : base(message) { } } public class PriceRequiredException : Exception { public PriceRequiredException() : base("Price is required") { } } public class InvalidPriceException : Exception { public InvalidPriceException(string message) : base(message) { } } ``` -------------------------------- ### Recommended Setup Pattern with DI and Nullable Reference Types Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Illustrates setting up Light.GuardClauses in a C# application, including enabling nullable reference types and validating dependencies injected via a service container. It also shows chaining multiple guard clauses for input validation. ```csharp // Program.cs or startup using Light.GuardClauses; // Enable nullable reference types #nullable enable // Configure services (example with DI) public class ServiceContainer { private readonly ILogger _logger; private readonly IRepository _repository; public ServiceContainer(ILogger? logger, IRepository? repository) { // Validate dependencies immediately _logger = logger.MustNotBeNull(); _repository = repository.MustNotBeNull(); } } // Use in application code public class UserService { public void CreateUser(string? name, string? email) { // Chain validations for clarity var validName = name .MustNotBeNullOrWhiteSpace() .MustHaveMinimumLength(2) .MustHaveMaximumLength(100); var validEmail = email .MustNotBeNullOrWhiteSpace() .MustBeEmailAddress(); // Proceed with confidence CreateUserInDatabase(validName, validEmail); } } ``` -------------------------------- ### Validating Guid and Range with Light.GuardClauses Source: https://github.com/feo2x/light.guardclauses/wiki/Home Demonstrates validating a Guid parameter with MustNotBeEmpty and an integer parameter with MustBeIn for a specified range. ```csharp public void SetMovieRating(Guid movieId, int numberOfStars) { movieId.MustNotBeEmpty(); numberOfStars.MustBeIn(Range.FromInclusive(0).ToInclusive(5)); var movie = _movieRepo.GetById(movieId); movie.AddRating(numberOfStars); } ``` -------------------------------- ### Example usage of MustNotBeEmpty GUID check Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Shows how to use MustNotBeEmpty to ensure a GUID is valid before proceeding with an operation, like updating a repository record. ```csharp public void ProcessRecord(Guid id) { var validId = id.MustNotBeEmpty(); _repository.Update(validId); } ``` -------------------------------- ### FluentValidation Integration Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Demonstrates integrating Light.GuardClauses with FluentValidation for robust validation. Ensures the object is not null before applying FluentValidation rules. ```csharp using Light.GuardClauses; using FluentValidation; public class UserValidator : AbstractValidator { public UserValidator() { RuleFor(u => u.Name) .NotEmpty().WithMessage("Name is required") .MinimumLength(2).WithMessage("Name must be at least 2 characters"); RuleFor(u => u.Email) .NotEmpty().WithMessage("Email is required") .EmailAddress().WithMessage("Invalid email format"); } } public class UserService { private readonly UserValidator _validator; public void CreateUser(User? user) { // Guard clause ensures object exists var validUser = user.MustNotBeNull(); // FluentValidation handles business rules var result = _validator.Validate(validUser); if (!result.IsValid) throw new ValidationException(result.Errors); _repository.Add(validUser); } } ``` -------------------------------- ### Polly Resilience Integration Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Shows how to use Light.GuardClauses with Polly for resilient API calls. Validates the URL before initiating retry policies to avoid retrying validation failures. ```csharp using Polly; using Light.GuardClauses; public class ResilientDataService { private readonly IAsyncPolicy _retryPolicy; public ResilientDataService() { // Validate input before retrying _retryPolicy = Policy .Handle() .OrResult(r => r == null) .Retry(3); } public async Task FetchWithRetryAsync(string? url) { // Validate eagerly, don't retry validation failures var validUrl = url.MustNotBeNullOrWhiteSpace(); // Retry only on transient failures var result = await _retryPolicy.ExecuteAsync(async () => await FetchAsync(validUrl)); return result.MustNotBeNull(); } private async Task FetchAsync(string url) { /* ... */ } } ``` -------------------------------- ### Type Checks Examples Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Illustrates type checking and validation methods, including type casting and enum validation. ```csharp var handler = handler.MustImplements(typeof(IEventHandler<>)); var enumValue = enumValue.MustBeValidEnumValue(); ``` -------------------------------- ### Ensure String Does Not Start With Prefix Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/string-checks.md Use this method to validate that a string parameter does not start with a specified prefix. It throws a StringStartsWithException if the condition is not met or ArgumentNullException if the parameter is null. ```csharp public static string MustNotStartWith( this string? parameter, string prefix, string? parameterName = null, string? message = null ) ``` -------------------------------- ### Native AOT Compatible Service Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Illustrates a service designed for Native AOT compilation with .NET 8. Demonstrates that all Light.GuardClauses assertions are AOT-safe and resolved at compile time. ```csharp using Light.GuardClauses; // This class is safe for Native AOT compilation public class AotCompatibleService { public void Process(string? input, int? count) { // All assertions work in AOT: var validInput = input.MustNotBeNullOrWhiteSpace(); var validCount = count.MustHaveValue(); // No reflection needed - everything resolved at compile time DoWork(validInput, validCount); } private void DoWork(string input, int count) { /* ... */ } } // AOT Project Setup (.csproj) /* true net8.0 */ ``` -------------------------------- ### Ensure GUID is not empty Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Validates that the provided GUID is not the default empty GUID. Throws an exception if it is empty. Optional parameter name and custom message can be provided. ```csharp public static Guid MustNotBeEmpty( this Guid parameter, string? parameterName = null, string? message = null ) ``` -------------------------------- ### ReSharper Integration Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Demonstrates how ReSharper recognizes guard clause validations, preventing false warnings for null references and multiple enumerations. ```csharp public void ValidateCollection(IEnumerable? items) { var validated = items.MustNotBeNullOrEmpty(); // ReSharper recognizes validated is non-null var first = validated.FirstOrDefault(); // No warning // ReSharper recognizes no enumeration happens var count = validated.Count(); // No "Possible multiple enumeration" warning } ``` -------------------------------- ### Upgrade Guide: Version 13.x to 14.0.0 Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Provides the specific code change required when upgrading from Light.GuardClauses version 13.x to 14.0.0 due to the relocation of the `Check.Contains` method. ```csharp // Before (13.x) using Light.GuardClauses; var valid = text.Check.Contains(searchText); // After (14.0.0+) using Light.GuardClauses.FrameworkExtensions; var valid = text.Check.Contains(searchText); ``` -------------------------------- ### Dependency Registration in DI Container Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Example of registering services in an IServiceCollection. Light.GuardClauses requires no explicit registration; constructor validation occurs automatically when services are instantiated. ```csharp // Program.cs or Startup.cs public void ConfigureServices(IServiceCollection services) { // Light.GuardClauses requires no registration // Just add your services services.AddScoped(); services.AddScoped(); services.AddScoped(); // When ApplicationService is instantiated, constructor validation happens } ``` -------------------------------- ### IsEmpty Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Checks if the GUID is empty (all zeros). ```APIDOC ## IsEmpty ### Description Checks if the GUID is empty (all zeros). ### Method `IsEmpty` (extension method for `Guid`) ### Parameters #### Path Parameters - **guid** (Guid) - Required - The GUID to check ### Response #### Success Response - **bool** — True if GUID equals Guid.Empty ### Example ```csharp if (id.IsEmpty()) { return "No ID provided"; } ``` ``` -------------------------------- ### Example usage of MustContainSubstring Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Demonstrates validating a URL by ensuring it contains a specific domain using MustNotBeNullOrEmpty and MustContainSubstring. ```csharp public void ValidateUrl(string? url) { var valid = url .MustNotBeNullOrEmpty() .MustContainSubstring("example.com"); _config.Url = valid; } ``` -------------------------------- ### C# String Must Start With Prefix Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/string-checks.md Ensures a string begins with a specified prefix. Throws StringDoesNotStartException if the prefix is not found or ArgumentNullException if the string is null. ```csharp public static string MustStartWith( this string? parameter, string prefix, string? parameterName = null, string? message = null ) ``` ```csharp public void SetUrl(string? url) { var validUrl = url.MustStartWith("https://"); _config.Url = validUrl; } ``` -------------------------------- ### MustNotBeEmpty Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Ensures that the GUID is not empty. ```APIDOC ## MustNotBeEmpty ### Description Ensures that the GUID is not empty. ### Method `MustNotBeEmpty` (extension method for `Guid`) ### Parameters #### Path Parameters - **parameter** (Guid) - Required - The GUID to validate - **parameterName** (string?) - Optional - The name of the parameter - **message** (string?) - Optional - Custom exception message ### Response #### Success Response - **Guid** — The validated non-empty GUID ### Throws - `EmptyGuidException` — When GUID is Guid.Empty ### Example ```csharp public void ProcessRecord(Guid id) { var validId = id.MustNotBeEmpty(); _repository.Update(validId); } ``` ``` -------------------------------- ### Fluent Range Definition Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/types.md Demonstrates the fluent API for defining a range, starting with the lower boundary and then specifying the upper boundary. ```csharp var range = Range .FromInclusive(0) .ToExclusive(100); // [0, 100) ``` -------------------------------- ### Async Validation Pattern Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Demonstrates using guard clauses for both synchronous and asynchronous validation steps within an async method. Includes validation before and after async operations like fetching data or checking existence. ```csharp public class AsyncDataProcessor { public async Task ProcessAsync(string? data) { // Synchronous validation first (cheap) var validData = data .MustNotBeNullOrWhiteSpace() .MustHaveMinimumLength(5); // Then do async work var retrieved = await FetchDataAsync(validData); // More validation after async work var processed = retrieved .MustNotBeNull() .Validate(); return processed; } public async Task UpdateAsync(int? id, string? name) { // Validate before async operations var validId = id.MustHaveValue(); var validName = name.MustNotBeNullOrWhiteSpace(); // Check existence asynchronously var exists = await ExistsAsync(validId); if (!exists) throw new NotFoundException($"Item {validId} not found"); // Update with validated values await SaveAsync(validId, validName); } private async Task ExistsAsync(int id) { /* ... */ } private async Task SaveAsync(int id, string name) { /* ... */ } } ``` -------------------------------- ### Guard Clauses Extension Method Signature Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/README.md Provides an example signature for a Guard Clauses extension method. Demonstrates the common pattern of `parameter.MustXxx(constraint)` and generic type constraints. ```csharp // Pattern: parameter.MustXxx(constraint) public static T MustNotBeNull(this T? parameter) where T : class public static string MustNotBeNullOrEmpty(this string? parameter) public static int MustBeGreaterThan(this int parameter, int lower) ``` -------------------------------- ### MustBeFileExtension Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/uri-checks.md Ensures that the string is a valid file extension (starts with a dot). An overload allows specifying a list of allowed extensions. ```APIDOC ## MustBeFileExtension ### Description Ensures that the string is a valid file extension (starts with dot). ### Method Signature `public static string MustBeFileExtension(this string? parameter, string? parameterName = null, string? message = null)` ### Parameters #### Path Parameters - **parameter** (string?) - Required - The extension to validate - **parameterName** (string?) - Optional - The name of the parameter - **message** (string?) - Optional - Custom exception message ### Returns string — The validated file extension ### Throws - `StringException` — When string is not a valid file extension - `ArgumentNullException` — When parameter is null ### Example ```csharp public void SetFileExtension(string? ext) { var valid = ext.MustBeFileExtension(); _file.Extension = valid; } ``` ## MustBeFileExtension (with allowed extensions) ### Description Validates that the extension is in the allowed list. ### Method Signature `public static string MustBeFileExtension(this string? parameter, IEnumerable allowedExtensions, StringComparisonType comparisonType = StringComparisonType.OrdinalIgnoreCase, string? parameterName = null, string? message = null)` ### Parameters #### Path Parameters - **parameter** (string?) - Required - The extension to validate - **allowedExtensions** (IEnumerable) - Required - A list of allowed extensions - **comparisonType** (StringComparisonType) - Optional - The type of string comparison to use (default: OrdinalIgnoreCase) - **parameterName** (string?) - Optional - The name of the parameter - **message** (string?) - Optional - Custom exception message ### Example ```csharp var ext = input.MustBeFileExtension(new[] { ".jpg", ".png", ".gif" }); ``` ``` -------------------------------- ### Range Usage Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/types.md Illustrates creating an inclusive-exclusive range and checking if a value falls within it. Also shows integration with assertion methods. ```csharp // Create an inclusive-exclusive range: [0, 100) var range = new Range(0, 100, true, false); // Check if value is in range if (range.IsValueWithinRange(50)) { Console.WriteLine("Value is valid"); } // Use with assertion methods var rating = userInput.MustBeIn(Range.InclusiveBetween(0, 5)); ``` -------------------------------- ### C# String Must Be Trimmed at Start Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/string-checks.md Ensures a string has no leading whitespace. Throws StringException if leading whitespace is present or ArgumentNullException if the string is null. ```csharp public static string MustBeTrimmedAtStart( this string? parameter, string? parameterName = null, string? message = null ) ``` -------------------------------- ### ReSharper Contract Annotation Example Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Demonstrates how ReSharper understands Light.GuardClauses assertions like MustNotBeNullOrEmpty, preventing potential null reference and multiple enumeration warnings. ```csharp public class DataProcessor { public void Process(IEnumerable? items) { var validated = items.MustNotBeNullOrEmpty(); // ReSharper understands: // 1. Method returns non-null IEnumerable // 2. Method does not enumerate the collection multiple times var first = validated.FirstOrDefault(); // No "Possible null reference" var count = validated.Count(); // No "Possible multiple enumeration" foreach (var item in validated) { Console.WriteLine(item); // No "Possible multiple enumeration" } } } ``` -------------------------------- ### Multiple Guard Clauses for Method Parameters Source: https://github.com/feo2x/light.guardclauses/blob/dev/README.md Demonstrates using multiple guard clauses, MustNotBeEmpty() for Guid and MustBeIn() for an integer range, to validate method parameters. ```csharp public void SetMovieRating(Guid movieId, int numberOfStars) { movieId.MustNotBeEmpty(); numberOfStars.MustBeIn(Range.InclusiveBetween(0, 5)); var movie = _movieRepo.GetById(movieId); movie.AddRating(numberOfStars); } ``` -------------------------------- ### MustBeFileExtension - Basic Usage Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/uri-checks.md Ensures that the string is a valid file extension, starting with a dot. Throws StringException for invalid formats or ArgumentNullException if the parameter is null. ```csharp public static string MustBeFileExtension( this string? parameter, string? parameterName = null, string? message = null ) ``` ```csharp public void SetFileExtension(string? ext) { var valid = ext.MustBeFileExtension(); _file.Extension = valid; } ``` -------------------------------- ### IsFileExtension - Check Format Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/uri-checks.md Checks if the given string conforms to the format of a valid file extension (starts with a dot). Returns true if valid, false otherwise. ```csharp public static bool IsFileExtension(this string? @string) ``` -------------------------------- ### Basic Usage of GuardClauses Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Demonstrates the immediate use of GuardClauses methods after instantiation, requiring no explicit initialization. ```csharp using Light.GuardClauses; // No initialization needed - just use directly public class MyClass { private readonly IService _service; public MyClass(IService? service) { _service = service.MustNotBeNull(); // Use immediately } } ``` -------------------------------- ### Check if a GUID is empty Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/character-checks.md Determines if the provided GUID is the default empty GUID (all zeros). Returns true if it is empty, false otherwise. ```csharp public static bool IsEmpty(this Guid guid) ``` -------------------------------- ### Recommended Project File Settings Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Configures project settings for optimal C# development, including language version, nullable reference types, and warning treatment. ```xml 12 enable true ``` -------------------------------- ### Customize Exception Message for Empty GUID Source: https://github.com/feo2x/light.guardclauses/wiki/How-to-Structure-Your-Precondition-Checks Provide a custom message when an entity's ID is an empty GUID. This ensures clarity on the specific validation failure. ```csharp public class Entity { public Guid Id { get; } public Entity(Guid id) => Id = id.MustNotBeEmpty(message: "You cannot create an entity with an empty GUID."); } ``` -------------------------------- ### Customize Target Frameworks for Local Development Source: https://github.com/feo2x/light.guardclauses/wiki/How-to-Contribute-and-Build Create a `TargetFrameworks.props` file next to the test project to specify which .NET frameworks the tests should run against. This file is ignored by git. ```xml net6.0;net48 ``` -------------------------------- ### Internal Source Code Transformation for Frameworks Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Demonstrates how framework developers can use the single-file version of Light.GuardClauses for internal use. Shows internal assertions that are not part of the public API. ```csharp // light-guardclauses-internal.cs // Generated from Light.GuardClauses.SourceCodeTransformation namespace MyFramework.Internal; // All methods are internal, no public API internal static partial class Check { internal static T MustNotBeNull(this T? parameter) where T : class { if (parameter is null) throw new ArgumentNullException(); return parameter; } // ... other assertions as internal } // Usage in your framework internal class MyService { internal MyService(ILogger? logger) { // Uses internal Check methods, not public package Logger = logger.MustNotBeNull(); } internal ILogger Logger { get; } } ``` -------------------------------- ### Creating Range Instances for Assertions Source: https://github.com/feo2x/light.guardclauses/wiki/Overview-of-All-Assertions Demonstrates how to create range instances using the fluent API for use with range-based assertions like MustBeIn. ```csharp starRating.MustBeIn(Range.FromExclusive(0).ToInclusive(5)); ``` ```csharp starRating.MustBeIn(Range.InclusiveBetween(1, 5)); ``` -------------------------------- ### Manually Create Exceptions Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/errors.md Illustrates different ways to manually instantiate custom exceptions, including auto-parameter capture, explicit parameter names, custom messages, and custom exception factories. ```csharp // With auto-parameter name capture (C# 10+) var validated = value.MustBeGreaterThan(0); // With explicit parameter name var validated = value.MustBeGreaterThan(0, nameof(value)); // With custom message var validated = value.MustBeGreaterThan(0, message: "Value must be positive"); // With custom exception factory var validated = value.MustBeGreaterThan(0, () => new ArgumentOutOfRangeException("Value must be positive")); ``` -------------------------------- ### MustBeTrimmed Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/string-checks.md Ensures that the string has no leading or trailing whitespace. This method validates that the string does not start or end with any whitespace characters. ```APIDOC ## MustBeTrimmed ### Description Ensures that the string has no leading or trailing whitespace. ### Method Signature ```csharp public static string MustBeTrimmed(string? parameter, string? parameterName = null, string? message = null) ``` ### Parameters #### Path Parameters - **parameter** (string?) - Required - The string to be checked - **parameterName** (string?) - Optional - The name of the parameter - **message** (string?) - Optional - Custom exception message ### Returns string — The validated trimmed string ### Throws - `StringException` — When string has leading or trailing whitespace - `ArgumentNullException` — When parameter is null ### Example ```csharp public void SetEmail(string? email) { var validEmail = email .MustNotBeNullOrWhiteSpace() .MustBeTrimmed(); _user.Email = validEmail; } ``` ``` -------------------------------- ### Get Count of Generic Enumerable Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/collection-checks.md Retrieves the item count for a generic IEnumerable. Use when working with strongly-typed collections. ```csharp public static int GetCount(this IEnumerable enumerable) ``` -------------------------------- ### Mocking Dependencies with Guard Clauses Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Illustrates how guard clauses can be used to validate dependencies during object construction, failing early if null dependencies are provided. ```csharp using Moq; public class ServiceTests { [Fact] public void Service_WithNullRepository_ThrowsImmediately() { // Guard clauses fail during construction Assert.Throws(() => new MyService( repository: null, // Guard clause triggers here logger: Mock.Of())); } [Fact] public void Service_WithValidDependencies_Constructs() { var mockRepo = Mock.Of(); var mockLogger = Mock.Of(); // No exception - validation passes var service = new MyService(mockRepo, mockLogger); Assert.NotNull(service); } } ``` -------------------------------- ### Character Checks Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Provides methods for character classification, newline validation, GUID checks, substring operations, and reference checks. ```APIDOC ## Character Checks ### Description Methods for character classification, newline validation, GUID checks, substring operations, and reference checks. ### Methods * `IsDigit()`, `IsLetter()`, `IsLetterOrDigit()`, `IsWhiteSpace()`, `IsNewLine()` * `MustBeNewLine()` * `IsEmpty()`, `MustNotBeEmpty()` * `MustContainSubstring()`, `MustNotContainSubstring()` * `MustBeSubstringOf()`, `MustNotBeSubstringOf()`, `IsSubstringOf()` * `IsSameAs()`, `MustNotBeSameAs()` ### Example Use Cases ```csharp var guid = guid.MustNotBeEmpty(); var substring = substring.MustBeSubstringOf(text, StringComparisonType.OrdinalIgnoreCase); ``` ``` -------------------------------- ### Using the Primary Namespace for Assertions Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/README.md Shows how to import the primary namespace 'Light.GuardClauses' for direct access to all assertion methods. ```csharp using Light.GuardClauses; value.MustNotBeNull(); // Direct access to all assertions ``` -------------------------------- ### Constructor Injection with Guard Clauses Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Shows how to validate all dependencies immediately upon object instantiation using guard clauses in the constructor. Ensures dependencies like ILogger, IRepository, and IEmailService are not null, and TimeSpan is positive. ```csharp public class ApplicationService { private readonly ILogger _logger; private readonly IRepository _repository; private readonly IEmailService _emailService; private readonly TimeSpan _timeout; public ApplicationService( ILogger? logger, IRepository? repository, IEmailService? emailService, TimeSpan timeout) { // Validate all dependencies immediately _logger = logger.MustNotBeNull(); _repository = repository.MustNotBeNull(); _emailService = emailService.MustNotBeNull(); _timeout = timeout.MustBeGreaterThan(TimeSpan.Zero); } } ``` -------------------------------- ### Count Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/collection-checks.md Efficiently gets the number of items in an enumerable collection. It optimizes for `ICollection` types and falls back to LINQ for others. ```APIDOC ## Count ### Description Gets the item count of the enumerable, handling both `ICollection` and LINQ enumerables efficiently. ### Method Signature ```csharp public static int Count(this IEnumerable enumerable) ``` ### Parameters #### Path Parameters - **enumerable** (IEnumerable) - Required - The collection to count ### Returns int - The number of items in the enumerable ``` -------------------------------- ### Documentation File Structure Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Overview of the directory structure for the Light.GuardClauses documentation, indicating the purpose of each markdown file. ```text /output/ ├── README.md ← START HERE ├── INDEX.md ← This file ├── Configuration.md ← Setup and installation ├── Types.md ← Type definitions ├── Errors.md ← Exception reference ├── advanced-features.md ← Advanced patterns └── api-reference/ ← API documentation by category ├── null-checks.md ├── string-checks.md ├── collection-checks.md ├── comparison-checks.md ├── type-checks.md ├── uri-checks.md ├── character-checks.md └── common-patterns.md ``` -------------------------------- ### String Comparison with OrdinalIgnoreCase Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/types.md Example of using StringComparisonType.OrdinalIgnoreCase for case-insensitive substring searching. Ensures that the search is not affected by the current culture's rules. ```csharp var substring = search .MustContainSubstring(query, StringComparisonType.OrdinalIgnoreCase); ``` -------------------------------- ### Method Chaining and Constructor Validation Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Illustrates common patterns like method chaining for sequential validation and validating constructor parameters. ```csharp // Method chaining var user = name .MustNotBeNullOrWhiteSpace() .MustHaveMinimumLength(2) .MustHaveMaximumLength(100); // Constructor validation public class Service { public Service(ILogger? logger, IRepository? repo) { Logger = logger.MustNotBeNull(); Repository = repo.MustNotBeNull(); } } ``` -------------------------------- ### Add Light.GuardClauses via csproj Package Reference Source: https://github.com/feo2x/light.guardclauses/blob/dev/README.md Reference the Light.GuardClauses NuGet package in your csproj file. ```xml ``` -------------------------------- ### Get Count of Enumerable Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/collection-checks.md Efficiently retrieves the number of items in an enumerable, supporting both ICollection and LINQ collections. Use when the exact size is needed. ```csharp public static int Count(this IEnumerable enumerable) ``` -------------------------------- ### Integrate Light.GuardClauses in C# Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Follow these steps to add the Light.GuardClauses NuGet package, include the necessary using statement, enable nullable reference types in your project file, and apply the clauses in your code. ```csharp // 1. Add NuGet package // dotnet add package Light.GuardClauses // 2. Using statement (namespace) using Light.GuardClauses; // 3. Enable nullable reference types in .csproj // // enable // // 4. Use in code public class Example { public Example(string? name, int age) { Name = name.MustNotBeNullOrWhiteSpace(); Age = age.MustBeGreaterThan(0).MustBeLessThan(150); } public string Name { get; } public int Age { get; } } ``` -------------------------------- ### Performance Comparison: Manual Validation vs. Guard Clause Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Shows that manual validation using if statements and Guard Clause validation compile to nearly identical IL, highlighting the performance equivalence. This encourages liberal use of assertions. ```csharp // These are equivalent in performance // Manual validation if (value == null) throw new ArgumentNullException(nameof(value)); var result = ProcessValue(value); // Guard Clause validation var result = ProcessValue(value.MustNotBeNull()); // Both compile to nearly identical IL ``` -------------------------------- ### MustNotBeDefault Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/api-reference/collection-checks.md Ensures that the value is not equal to its type's default value. This is useful for validating parameters that should not be the default value for their type, such as default GUIDs or null objects. ```APIDOC ## MustNotBeDefault ### Description Ensures that the value is not equal to its type's default value. ### Method Signature public static T MustNotBeDefault(this T parameter, string? parameterName = null, string? message = null) ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters Table | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | parameter | T | — | The value to check | | parameterName | string? | null | The name of the parameter | | message | string? | null | Custom exception message | ### Returns T — The validated value ### Throws - `ArgumentDefaultException` — When value equals default for type ### Example ```csharp public void SetId(Guid id) { var validId = id.MustNotBeDefault(); _entity.Id = validId; } ``` ``` -------------------------------- ### Basic Factory Pattern for Custom Exceptions Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Demonstrates using custom exception factories with assertion methods. Supports delegates with zero, one, or multiple parameters. ```csharp // Signature: Func var value = input.MustNotBeNull(() => new InvalidOperationException("User context not initialized")); // With parameters: Func var validated = items.MustNotBeNullOrEmpty((collection) => new ArgumentException($"Collection '{collection}' cannot be empty")); // With multiple parameters: Func var compared = current.MustBe(expected, (c, e) => new AssertionException($"Expected {e}, but got {c}")); ``` -------------------------------- ### Null Check with Light.GuardClauses in C# Constructor Source: https://github.com/feo2x/light.guardclauses/wiki/Home Shows how to use the MustNotBeNull extension method from Light.GuardClauses to simplify null parameter checks in a C# constructor. ```csharp public class Foo { private readonly IBar _bar; public Foo(IBar? bar) { _bar = bar.MustNotBeNull(); } } ``` -------------------------------- ### Measuring Assertion Overhead with BenchmarkDotNet Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Compares the performance overhead of manual null checks against Light.GuardClauses' MustNotBeNull assertion using BenchmarkDotNet. Results show no measurable difference, indicating full inlining. ```csharp using BenchmarkDotNet.Attributes; using Light.GuardClauses; [MemoryDiagnoser] public class AssertionBenchmarks { private string _testValue = "test"; [Benchmark(Baseline = true)] public string ManualValidation() { if (_testValue == null) throw new ArgumentNullException(nameof(_testValue)); return _testValue; } [Benchmark] public string GuardClauseValidation() { return _testValue.MustNotBeNull(); } // Results on .NET 8 (Release): // ManualValidation: ~0.5 ns, 0 B allocated // GuardClauseValidation: ~0.5 ns, 0 B allocated // No measurable difference - fully inlined } ``` -------------------------------- ### Validating HttpClient and Uri with Light.GuardClauses Source: https://github.com/feo2x/light.guardclauses/wiki/Home Shows how to use MustNotBeNull for HttpClient and MustBeHttpOrHttpsUrl for a Uri parameter in a class constructor. ```csharp public class WebGateway { private readonly HttpClient _httpClient; private readonly Uri _targetUrl; public WebGateway(HttpClient? httpClient, Uri? targetUrl) { _httpClient = httpClient.MustNotBeNull(); _targetUrl = targetUrl.MustBeHttpOrHttpsUrl(); } } ``` -------------------------------- ### Customizing Assertions with Optional Parameters Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/README.md Demonstrates how to customize assertions with optional parameters like explicit parameter names, custom error messages, or custom exception factories. ```csharp // Auto-captured parameter name (C# 10+) value.MustBeGreaterThan(0) ``` ```csharp // Explicit parameter name (all C# versions) value.MustBeGreaterThan(0, nameof(value)) ``` ```csharp // Custom error message value.MustBeGreaterThan(0, message: "Value must be positive") ``` ```csharp // Custom exception factory value.MustBeGreaterThan(0, () => new DomainException("...")) ``` -------------------------------- ### Custom Exception Constructor Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/types.md Illustrates the constructor for custom exceptions in Light.GuardClauses, which accepts an optional parameter name and a custom message. Use to provide specific details about validation failures. ```csharp public CustomException(string? parameterName = null, string? message = null) ``` -------------------------------- ### Native AOT Compatible Usage Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Demonstrates the usage of Light.GuardClauses within a Native AOT compatible application, ensuring assertions work without runtime reflection. ```csharp // Can be used in Native AOT applications using Light.GuardClauses; public class AotCompatibleClass { public AotCompatibleClass(string? input) { Input = input.MustNotBeNullOrWhiteSpace(); } public string Input { get; } } ``` -------------------------------- ### Handle UriException Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/errors.md Demonstrates how to catch a UriException when a URI scheme is not HTTP or HTTPS. ```csharp try { var uri = new Uri("ftp://example.com"); var validated = uri.MustBeHttpOrHttpsUrl(); } catch (UriException ex) { Console.WriteLine("URI must use HTTP or HTTPS"); } ``` -------------------------------- ### Refactored Method Using Guard Clauses Source: https://github.com/feo2x/light.guardclauses/wiki/Trivia This C# code shows the refactored version of the previous example, utilizing guard clauses to simplify the branching logic. Each condition immediately returns if met, improving readability. ```csharp public double GetPayAmount() { if (_isDead) return DeadAmount(); if (_isSeparated) return SeparatedAmount(); if (_isRetired) return RetiredAmount(); return NormalPayAmount(); }; ``` -------------------------------- ### Reference Light.GuardClauses in csproj Source: https://github.com/feo2x/light.guardclauses/wiki/Home Add this XML element to your .csproj file to reference the Light.GuardClauses NuGet package. ```xml ``` -------------------------------- ### Basic Input Validation in C# Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/README.md Demonstrates basic input validation for user properties like name, email, and age using Guard Clauses. Ensures parameters are not null, whitespace, or out of specified ranges. ```csharp using Light.GuardClauses; public class UserService { private readonly IRepository _repository; public UserService(IRepository? repository) { _repository = repository.MustNotBeNull(); } public void CreateUser(string? name, string? email, int age) { var validName = name .MustNotBeNullOrWhiteSpace() .MustHaveMinimumLength(2) .MustHaveMaximumLength(100); var validEmail = email .MustNotBeNullOrWhiteSpace() .MustBeEmailAddress(); var validAge = age .MustBeGreaterThan(0) .MustBeLessThan(150); _repository.AddUser(validName, validEmail, validAge); } } ``` -------------------------------- ### Enable Analyzer Checks in Project Configuration Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Configure your project to enable analyzer checks by setting the AnalysisLevel to latest and EnforceCodeStyleInBuild to true. Ensure warnings are treated as errors. ```xml latest true true ``` -------------------------------- ### Standard Null Check in C# Constructor Source: https://github.com/feo2x/light.guardclauses/wiki/Home Demonstrates the traditional approach to checking for null parameters in a C# constructor using an if statement and throwing ArgumentNullException. ```csharp public class Foo { private readonly IBar _bar; public Foo(IBar? bar) { if (bar == null) throw new ArgumentNullException(nameof(bar)); _bar = bar; } } ``` -------------------------------- ### URI Checks API Reference Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/DOCUMENTATION_SUMMARY.txt Documentation for URI, email, and format assertions, featuring over 25 overloaded methods for validating string formats. ```APIDOC ## URI Checks API Reference ### Description Offers assertion methods for validating string formats, including URIs, email addresses, and other common patterns. This section includes over 25 overloaded methods. ### Methods This document details methods for checking if a string conforms to specific format requirements like valid URIs or email addresses. ### Parameters Parameters typically include the string value to validate and an optional custom exception message. ### Return Value Methods return `void` or throw an exception if the validation fails. ### Exception Specifications Details custom exception classes thrown for validation failures, including trigger conditions and hierarchy. ``` -------------------------------- ### Contextual Error Messages with Custom Exceptions Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Shows how to provide contextual error messages, including details from other variables, when throwing exceptions. ```csharp public class ConfigurationValidator { public static void ValidateDatabase(string? connectionString, string? databaseName) { var validConnection = connectionString.MustNotBeNullOrWhiteSpace( message: "Database connection string must be configured in appsettings.json"); var validDatabase = databaseName.MustNotBeNullOrWhiteSpace(() => new InvalidOperationException( $"Database name required. Connection: {validConnection}")); } public static void ValidateServiceEndpoint(Uri? endpoint) { endpoint.MustBeHttpsUrl(() => new InvalidOperationException( "Service endpoint must use HTTPS for security. " + "Update configuration to use a secure URL. " + $"Current value: {endpoint}")); } } ``` -------------------------------- ### Default Settings for Source Code Transformation Source: https://github.com/feo2x/light.guardclauses/wiki/Including-Light.GuardClauses-as-source-code This JSON configuration file defines the default settings for customizing the generated single-source-code file of Light.GuardClauses. It controls aspects like type visibility, namespaces, and the inclusion of various annotations and attributes. ```json { "changePublicTypesToInternalTypes": true, "baseNamespace": "Light.GuardClauses", "removeContractAnnotations": false, "includeJetBrainsAnnotationsUsing": true, "includeJetBrainsAnnotations": true, "includeVersionComment": true, "removeOverloadsWithExceptionFactory": false, "includeCodeAnalysisNullableAttributes": true, "includeValidatedNotNullAttribute": true, "removeValidatedNotNull": false, "removeDoesNotReturn": false, "removeNotNullWhen": false, "includeCallerArgumentExpressionAttribute": true, "removeCallerArgumentExpressions": false } ``` -------------------------------- ### Unit Testing Guard Clause Exceptions Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/advanced-features.md Demonstrates how to test guard clauses that are expected to throw specific exceptions like ArgumentNullException or InvalidEmailAddressException. ```csharp using Xunit; using Light.GuardClauses; public class UserServiceTests { [Fact] public void CreateUser_WithNullName_ThrowsArgumentNullException() { // Guard clauses throw ArgumentNullException var service = new UserService(); Assert.Throws(() => service.CreateUser(null, "user@example.com")); } [Fact] public void CreateUser_WithEmptyEmail_ThrowsException() { var service = new UserService(); Assert.Throws(() => service.CreateUser("John", "")); } [Theory] [InlineData(0)] [InlineData(-1)] public void SetAge_WithInvalidAge_ThrowsArgumentOutOfRangeException(int age) { var user = new User { Name = "John" }; Assert.Throws(() => user.SetAge(age)); } } ``` -------------------------------- ### Analyzer Support for GuardClauses Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Shows how Light.GuardClauses works with .NET analyzers, suppressing warnings like CA1062 after validation. ```csharp public void ProcessItem(Item? item) // CA1062 warning would occur here { item.MustNotBeNull(); // Analyzer recognizes validation // No more CA1062 warning for this method DoSomething(item.Id); // Safe to use } ``` -------------------------------- ### GuardClauses with Nullable Reference Types Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/configuration.md Illustrates how Light.GuardClauses integrates with C# nullable reference types, ensuring validated parameters are recognized as non-null. ```csharp // With nullable reference types enabled public void ProcessUser(User? user) { var validUser = user.MustNotBeNull(); // Returns User (non-null) // Analyzer recognizes validUser cannot be null Console.WriteLine(validUser.Name); // No warning } ``` -------------------------------- ### Basic Null and Empty Checks Source: https://github.com/feo2x/light.guardclauses/blob/dev/_autodocs/INDEX.md Use these assertions to validate that references are not null and that strings or collections are not empty or whitespace. Ensure the variable is not null before calling further assertions on it. ```csharp var service = service.MustNotBeNull(); var username = username.MustNotBeNullOrWhiteSpace(); var items = items.MustNotBeNullOrEmpty(); ```