< Summary

Information
Class: SwiftCollections.SwiftThrowHelper
Assembly: SwiftCollections
File(s): /home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Utility/SwiftThrowHelper.cs
Line coverage
97%
Covered lines: 45
Uncovered lines: 1
Coverable lines: 46
Total lines: 250
Line coverage: 97.8%
Branch coverage
93%
Covered branches: 43
Total branches: 46
Branch coverage: 93.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/SwiftCollections/SwiftCollections/src/SwiftCollections/Utility/SwiftThrowHelper.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Diagnostics.CodeAnalysis;
 4using System.Runtime.CompilerServices;
 5
 6namespace SwiftCollections;
 7
 8/// <summary>
 9/// Provides helper methods for throwing common exceptions in a consistent and efficient manner.
 10/// These methods are intended to simplify argument and state validation throughout the codebase.
 11/// </summary>
 12/// <remarks>
 13/// This class centralizes exception throwing logic to improve code clarity and reduce repetitive validation code.
 14/// Methods are typically inlined by the compiler to minimize performance overhead.
 15/// </remarks>
 16public static class SwiftThrowHelper
 17{
 18    #region Null Argument Validation
 19
 20    /// <summary>
 21    /// Throws an ArgumentNullException if the provided argument is null.
 22    /// </summary>
 23    /// <param name="argument">The argument to check for null.</param>
 24    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 25    /// <param name="message">An optional message to include in the exception.</param>
 26    /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
 27    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 28    public static void ThrowIfNull([NotNull] object? argument, string? paramName = null, string? message = null)
 29    {
 158230        if (argument is null)
 2831            ThrowArgumentNullException(paramName, message);
 155432    }
 33
 34    /// <summary>
 35    /// Throws an ArgumentNullException if the provided generic argument is null.
 36    /// This method is useful for validating reference types in a generic context where the type parameter may not be co
 37    /// </summary>
 38    /// <typeparam name="T">The type of the argument to check.</typeparam>
 39    /// <param name="argument">The argument to check for null.</param>
 40    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 41    /// <param name="message">An optional message to include in the exception.</param>
 42    /// <exception cref="ArgumentNullException">Thrown when the argument is null.</exception>
 43    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 44    public static void ThrowIfNullGeneric<T>([NotNull] T argument, string? paramName = null, string? message = null)
 45    {
 43645746        if (argument is null)
 447            ThrowArgumentNullException(paramName, message);
 43645348    }
 49
 50    /// <summary>
 51    /// Throws an exception if the specified value is null and nulls are not allowed for TValue.
 52    /// </summary>
 53    /// <param name="value">The value to check.</param>
 54    /// <param name="defaultValue">A default value of type TValue used to determine if nulls are illegal.</param>
 55    /// <param name="message">An optional message to include in the exception.</param>
 56    /// <exception cref="ArgumentNullException">The value is null and TValue is a value type.</exception>
 57    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 58    public static void ThrowIfNullAndNullsAreIllegal<TValue>(object? value, TValue? defaultValue, string? message = null
 59    {
 560        if (value == null && !(defaultValue == null))
 061            ThrowArgumentNullException(nameof(value), message);
 562    }
 63
 64    [DoesNotReturn]
 65    [MethodImpl(MethodImplOptions.NoInlining)]
 66    private static void ThrowArgumentNullException(string? paramName, string? message = null) =>
 3267        throw new ArgumentNullException(paramName, message);
 68
 69    #endregion
 70
 71    #region Out of Range Validation
 72
 73    /// <summary>
 74    /// Throws an ArgumentOutOfRangeException if the specified value is negative, indicating that the argument must be a
 75    /// </summary>
 76    /// <param name="value">The value to check.</param>
 77    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 78    /// <param name="message">An optional message to include in the exception.</param>
 79    /// <exception cref="ArgumentOutOfRangeException">Thrown when the value is negative.</exception>
 80    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 81    public static void ThrowIfNegative(int value, string? paramName = null, string? message = null)
 82    {
 13183        if (value < 0)
 284            ThrowArgumentOutOfRangeException(paramName, value, message ?? $"{paramName} must be non-negative.");
 12985    }
 86
 87    /// <summary>
 88    /// Throws an ArgumentOutOfRangeException if the specified value is negative or zero, indicating that the argument m
 89    /// </summary>
 90    /// <param name="value">The value to check.</param>
 91    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 92    /// <param name="message">An optional message to include in the exception.</param>
 93    /// <exception cref="ArgumentOutOfRangeException">Thrown when the value is negative or zero.</exception>
 94    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 95    public static void ThrowIfNegativeOrZero(int value, string? paramName = null, string? message = null)
 96    {
 9597        if (value < 0 || value == 0)
 298            ThrowArgumentOutOfRangeException(paramName, value, message ?? $"{paramName} must be greater than zero.");
 9399    }
 100
 101    /// <summary>
 102    /// Throws an ArgumentOutOfRangeException if the specified condition is true.
 103    /// </summary>
 104    /// <param name="condition">The condition to evaluate.</param>
 105    /// <param name="actualValue">The value that caused the exception.</param>
 106    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 107    /// <param name="message">An optional message to include in the exception.</param>
 108    /// <exception cref="ArgumentOutOfRangeException">Thrown when the condition is true.</exception>
 109    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 110    public static void ThrowIfArgumentOutOfRange([DoesNotReturnIf(true)] bool condition, int actualValue, string? paramN
 111    {
 53112        if (condition)
 3113            ThrowArgumentOutOfRangeException(paramName, actualValue, message);
 50114    }
 115
 116    /// <summary>
 117    /// Throws an ArgumentOutOfRangeException if a copy destination index is outside [0, length].
 118    /// </summary>
 119    /// <param name="index">The destination index to check.</param>
 120    /// <param name="length">The destination length.</param>
 121    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 122    /// <param name="message">An optional message to include in the exception.</param>
 123    /// <exception cref="ArgumentOutOfRangeException">Thrown when the index is outside [0, length].</exception>
 124    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 125    public static void ThrowIfArrayIndexInvalid(int index, int length, string? paramName = null, string? message = null)
 126    {
 148127        if ((uint)index > (uint)length)
 6128            ThrowArgumentOutOfRangeException(paramName ?? nameof(index), index, message ?? "Array index is out of range.
 142129    }
 130
 131    [DoesNotReturn]
 132    [MethodImpl(MethodImplOptions.NoInlining)]
 133    private static void ThrowArgumentOutOfRangeException(string? paramName, object? actualValue, string? message = null)
 13134        throw new ArgumentOutOfRangeException(paramName, actualValue, message);
 135
 136    #endregion
 137
 138    #region Invalid State Validation
 139
 140    /// <summary>
 141    /// Throws an ArgumentException if the specified condition is true.
 142    /// </summary>
 143    /// <param name="condition">The condition to evaluate.</param>
 144    /// <param name="paramName">The name of the parameter that caused the exception.</param>
 145    /// <param name="message">An optional message to include in the exception.</param>
 146    /// <exception cref="ArgumentException">Thrown when the condition is true.</exception>
 147    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 148    public static void ThrowIfArgument([DoesNotReturnIf(true)] bool condition, string? paramName = null, string? message
 149    {
 147150        if (condition)
 27151            ThrowArgumentException(paramName, message);
 120152    }
 153
 154    [DoesNotReturn]
 155    [MethodImpl(MethodImplOptions.NoInlining)]
 156    private static void ThrowArgumentException(string? paramName, string? message = null) =>
 27157        throw new ArgumentException(message, paramName);
 158
 159    /// <summary>
 160    /// Throws an InvalidOperationException if the specified condition is true, indicating that the object is in an inva
 161    /// </summary>
 162    /// <param name="condition">The condition to evaluate.</param>
 163    /// <param name="objectName">The name of the object in an invalid state.</param>
 164    /// <param name="message">An optional message to include in the exception.</param>
 165    /// <exception cref="InvalidOperationException">Thrown when the condition is true, indicating an invalid state.</exc
 166    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 167    public static void ThrowIfTrue([DoesNotReturnIf(true)] bool condition, string? objectName = null, string? message = 
 168    {
 1796169        if (condition)
 33170            ThrowInvalidOperationException(objectName, message);
 1763171    }
 172
 173    [DoesNotReturn]
 174    [MethodImpl(MethodImplOptions.NoInlining)]
 175    private static void ThrowInvalidOperationException(string? objectName, string? message = null) =>
 33176        throw new InvalidOperationException(message ?? $"Object '{objectName}' is in an invalid state.");
 177
 178    /// <summary>
 179    /// Throws an ObjectDisposedException if the specified condition is true, indicating that the object has been dispos
 180    /// </summary>
 181    /// <param name="condition">The condition to evaluate.</param>
 182    /// <param name="objectName">The name of the object that has been disposed.</param>
 183    /// <param name="message">An optional message to include in the exception.</param>
 184    /// <exception cref="ObjectDisposedException">Thrown when the condition is true, indicating that the object has been
 185    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 186    public static void ThrowIfDisposed([DoesNotReturnIf(true)] bool condition, string? objectName = null, string? messag
 187    {
 203188        if (condition)
 13189            ThrowObjectDisposedException(objectName, message);
 190190    }
 191
 192    [DoesNotReturn]
 193    [MethodImpl(MethodImplOptions.NoInlining)]
 194    private static void ThrowObjectDisposedException(string? objectName, string? message = null) =>
 13195        throw new ObjectDisposedException(objectName, message ?? $"Object '{objectName}' has been disposed.");
 196
 197    /// <summary>
 198    /// Throws a KeyNotFoundException if the specified index is negative, indicating that the key is invalid for the cur
 199    /// </summary>
 200    /// <param name="index">The index to check.</param>
 201    /// <param name="key">The key associated with the index.</param>
 202    /// <param name="message">An optional message to include in the exception.</param>
 203    /// <exception cref="KeyNotFoundException">Thrown when the index is negative, indicating an invalid key.</exception>
 204    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 205    public static void ThrowIfKeyInvalid(int index, object? key = null, string? message = null)
 206    {
 4168207        if (index < 0)
 3208            ThrowKeyNotFoundException(index, key, message);
 4165209    }
 210
 211    /// <summary>
 212    /// Throws a KeyNotFoundException if the specified condition is true.
 213    /// </summary>
 214    /// <param name="condition">The condition to evaluate.</param>
 215    /// <param name="key">The key associated with the lookup.</param>
 216    /// <param name="message">An optional message to include in the exception.</param>
 217    /// <exception cref="KeyNotFoundException">Thrown when the condition is true.</exception>
 218    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 219    public static void ThrowIfKeyNotFound([DoesNotReturnIf(true)] bool condition, object? key = null, string? message = 
 220    {
 38221        if (condition)
 3222            ThrowKeyNotFoundException(-1, key, message);
 35223    }
 224
 225    [DoesNotReturn]
 226    [MethodImpl(MethodImplOptions.NoInlining)]
 227    private static void ThrowKeyNotFoundException(int index, object? key, string? message = null) =>
 6228        throw new KeyNotFoundException(message ?? $"Key not found: {key}");
 229
 230    /// <summary>
 231    /// Throws an IndexOutOfRangeException if the specified index is outside the valid range defined by count, indicatin
 232    /// </summary>
 233    /// <param name="index">The index to check.</param>
 234    /// <param name="count">The total number of elements in the collection.</param>
 235    /// <param name="message">An optional message to include in the exception.</param>
 236    /// <exception cref="IndexOutOfRangeException">Thrown when the index is outside the valid range.</exception>
 237    [MethodImpl(MethodImplOptions.AggressiveInlining)]
 238    public static void ThrowIfListIndexInvalid(int index, int count, string? message = null)
 239    {
 5040240        if ((uint)index >= (uint)count)
 11241            ThrowIndexOutOfRangeException(index, message);
 5029242    }
 243
 244    [DoesNotReturn]
 245    [MethodImpl(MethodImplOptions.NoInlining)]
 246    private static void ThrowIndexOutOfRangeException(int value, string? message = null) =>
 11247        throw new IndexOutOfRangeException(message ?? $"Index out of range: {value}");
 248
 249    #endregion
 250}