diff --git a/Code/Light.GuardClauses/Light.GuardClauses.csproj b/Code/Light.GuardClauses/Light.GuardClauses.csproj
index 7780ff0..845a5fe 100644
--- a/Code/Light.GuardClauses/Light.GuardClauses.csproj
+++ b/Code/Light.GuardClauses/Light.GuardClauses.csproj
@@ -1,59 +1,55 @@
-
+
-
- netstandard2.0;netstandard2.1;net8.0
- A lightweight .NET library for expressive Guard Clauses.
- Kenny Pflug
- Kenny Pflug
- enable
- true
- Copyright © Kenny Pflug 2016, 2025
- 12
- true
- true
- MIT
- light-logo.png
- https://github.com/feO2x/Light.GuardClauses
- https://github.com/feO2x/Light.GuardClauses.git
- git
- true
- true
- snupkg
- true
- Assertions;Preconditions;GuardClauses;DesignByContract;DbC
- true
- README.md
-
-Light.GuardClauses 13.0.0
---------------------------------
+
+ netstandard2.0;netstandard2.1;net8.0
+ A lightweight .NET library for expressive Guard Clauses.
+ Kenny Pflug
+ Kenny Pflug
+ enable
+ true
+ Copyright © Kenny Pflug 2016, 2025
+ 12
+ true
+ true
+ MIT
+ light-logo.png
+ https://github.com/feO2x/Light.GuardClauses
+ https://github.com/feO2x/Light.GuardClauses.git
+ git
+ true
+ true
+ snupkg
+ true
+ Assertions;Preconditions;GuardClauses;DesignByContract;DbC
+ true
+ README.md
+
+ Light.GuardClauses 13.1.0
+ --------------------------------
-- new assertions: IsApproximately<T>, IsLessThanOrApproximately<T>, IsGreaterThanOrApproximately<T>, MustBeApproximately, MustNotBeApproximately, MustBeLessThanOrApproximately, MustBeGreaterThanOrApproximately, IsEmptyOrWhiteSpace, IsFileExtension
-- email regex is now precompiled on .NET 8 and newer, the regex is compiled at runtime on .NET Standard 2.0 and 2.1
-- breaking: Throw class is now located in new namespace Light.GuardClauses.ExceptionFactory
-- breaking: Throw members regarding spans now only support ReadOnlySpan<T>, in keywords were removed
-- breaking: IsApproximately now uses less-than-or-equal-to operator (<=) instead of less-than operator (<)
-- breaking: Email regex is less strict and support additional patterns like domains with more than 3 letters (e.g. .info or .travel)
-
-
-
-
-
-
-
-
-
-
+ - new assertions for ImmutableArray<T>: MustNotBeDefaultOrEmpty, MustHaveLength, MustHaveLengthIn, MustHaveMinimumLength, MustHaveMaximumLength
+ - new dependency: System.Collections.Immutable
+
+
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Code/Version.props b/Code/Version.props
index 83928e4..e4e99d8 100644
--- a/Code/Version.props
+++ b/Code/Version.props
@@ -1,5 +1,5 @@
- 13.0.0
+ 13.1.0
\ No newline at end of file
diff --git a/Light.GuardClauses.SingleFile.cs b/Light.GuardClauses.SingleFile.cs
index d984d0b..758820c 100644
--- a/Light.GuardClauses.SingleFile.cs
+++ b/Light.GuardClauses.SingleFile.cs
@@ -1,5 +1,5 @@
/* ------------------------------
- Light.GuardClauses 13.0.0
+ Light.GuardClauses 13.1.0
------------------------------
License information for Light.GuardClauses
@@ -270,6 +270,50 @@ public static string MustNotContain([NotNull][ValidatedNotNull] this string? par
return parameter;
}
+ ///
+ /// Ensures that the does not contain the specified item, or otherwise throws an .
+ ///
+ /// The to be checked.
+ /// The item that must not be part of the .
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when contains .
+ ///
+ /// The default instance of cannot contain any items, so this method will not throw for default instances.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustNotContain(this ImmutableArray parameter, T item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ if (!parameter.IsDefault && parameter.Contains(item))
+ {
+ Throw.ExistingItem(parameter, item, parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the does not contain the specified item, or otherwise throws your custom exception.
+ ///
+ /// The to be checked.
+ /// The item that must not be part of the .
+ /// The delegate that creates your custom exception. and are passed to this delegate.
+ /// Your custom exception thrown when contains .
+ ///
+ /// The default instance of cannot contain any items, so this method will not throw for default instances.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [ContractAnnotation("exceptionFactory:null => halt")]
+ public static ImmutableArray MustNotContain(this ImmutableArray parameter, T item, Func, T, Exception> exceptionFactory)
+ {
+ if (!parameter.IsDefault && parameter.Contains(item))
+ {
+ Throw.CustomException(exceptionFactory, parameter, item);
+ }
+
+ return parameter;
+ }
+
///
/// Checks if the specified string is trimmed at the end, i.e. it does not end with
/// white space characters. Inputting an empty string will return true.
@@ -2764,6 +2808,42 @@ public static Uri MustHaveScheme([NotNull][ValidatedNotNull] this Uri? parameter
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsLessThanOrApproximately(this float value, float other) => value < other || value.IsApproximately(other);
+ ///
+ /// Ensures that the specified is not default or empty, or otherwise throws an .
+ ///
+ /// The to be checked.
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when is default or empty.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustNotBeDefaultOrEmpty(this ImmutableArray parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ if (parameter.IsDefaultOrEmpty)
+ {
+ Throw.EmptyCollection(parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the specified is not default or empty, or otherwise throws your custom exception.
+ ///
+ /// The to be checked.
+ /// The delegate that creates your custom exception. The is passed to this delegate.
+ /// Your custom exception thrown when is default or empty.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [ContractAnnotation("exceptionFactory:null => halt")]
+ public static ImmutableArray MustNotBeDefaultOrEmpty(this ImmutableArray parameter, Func, Exception> exceptionFactory)
+ {
+ if (parameter.IsDefaultOrEmpty)
+ {
+ Throw.CustomException(exceptionFactory, parameter);
+ }
+
+ return parameter;
+ }
+
///
/// Ensures that the specified URI has the "http" scheme, or otherwise throws an .
///
@@ -4227,6 +4307,46 @@ public static string MustHaveLengthIn([NotNull][ValidatedNotNull] this string? p
return parameter;
}
+ ///
+ /// Ensures that the 's length is within the specified range, or otherwise throws an .
+ ///
+ /// The to be checked.
+ /// The range where the 's length must be in-between.
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when the length of is not within the specified .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveLengthIn(this ImmutableArray parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ var length = parameter.IsDefault ? 0 : parameter.Length;
+ if (!range.IsValueWithinRange(length))
+ {
+ Throw.ImmutableArrayLengthNotInRange(parameter, range, parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the 's length is within the specified range, or otherwise throws your custom exception.
+ ///
+ /// The to be checked.
+ /// The range where the 's length must be in-between.
+ /// The delegate that creates your custom exception. and are passed to this delegate.
+ /// Your custom exception thrown when the length of is not within the specified range.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [ContractAnnotation("exceptionFactory:null => halt")]
+ public static ImmutableArray MustHaveLengthIn(this ImmutableArray parameter, Range range, Func, Range, Exception> exceptionFactory)
+ {
+ var length = parameter.IsDefault ? 0 : parameter.Length;
+ if (!range.IsValueWithinRange(length))
+ {
+ Throw.CustomException(exceptionFactory, parameter, range);
+ }
+
+ return parameter;
+ }
+
///
/// Ensures that the specified parameter is not the default value, or otherwise throws an
/// for reference types, or an for value types.
@@ -4402,6 +4522,47 @@ public static ReadOnlySpan MustBeShorterThan(this ReadOnlySpan paramete
return parameter;
}
+ ///
+ /// Ensures that the has at most the specified length, or otherwise throws an .
+ ///
+ /// The to be checked.
+ /// The maximum length the should have.
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when has more than the specified length.
+ /// The default instance of will be treated as having length 0.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveMaximumLength(this ImmutableArray parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ var parameterLength = parameter.IsDefault ? 0 : parameter.Length;
+ if (parameterLength > length)
+ {
+ Throw.InvalidMaximumImmutableArrayLength(parameter, length, parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the has at most the specified length, or otherwise throws your custom exception.
+ ///
+ /// The to be checked.
+ /// The maximum length the should have.
+ /// The delegate that creates your custom exception. and are passed to this delegate.
+ /// Your custom exception thrown when has more than the specified length.
+ /// The default instance of will be treated as having length 0.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveMaximumLength(this ImmutableArray parameter, int length, Func, int, Exception> exceptionFactory)
+ {
+ var parameterLength = parameter.IsDefault ? 0 : parameter.Length;
+ if (parameterLength > length)
+ {
+ Throw.CustomException(exceptionFactory, parameter, length);
+ }
+
+ return parameter;
+ }
+
///
/// Checks if the specified collection is null or empty.
///
@@ -4481,6 +4642,47 @@ public static string MustBeTrimmedAtEnd([NotNull][ValidatedNotNull] this string?
return parameter;
}
+ ///
+ /// Ensures that the has at least the specified length, or otherwise throws an .
+ ///
+ /// The to be checked.
+ /// The minimum length the should have.
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when has less than the specified length.
+ /// The default instance of will be treated as having length 0.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveMinimumLength(this ImmutableArray parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ var parameterLength = parameter.IsDefault ? 0 : parameter.Length;
+ if (parameterLength < length)
+ {
+ Throw.InvalidMinimumImmutableArrayLength(parameter, length, parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the has at least the specified length, or otherwise throws your custom exception.
+ ///
+ /// The to be checked.
+ /// The minimum length the should have.
+ /// The delegate that creates your custom exception. and are passed to this delegate.
+ /// Your custom exception thrown when has less than the specified length.
+ /// The default instance of will be treated as having length 0.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveMinimumLength(this ImmutableArray parameter, int length, Func, int, Exception> exceptionFactory)
+ {
+ var parameterLength = parameter.IsDefault ? 0 : parameter.Length;
+ if (parameterLength < length)
+ {
+ Throw.CustomException(exceptionFactory, parameter, length);
+ }
+
+ return parameter;
+ }
+
///
/// Ensures that the specified parameter is not null when is a reference type, or otherwise
/// throws an . PLEASE NOTICE: you should only use this assertion in generic contexts,
@@ -4720,6 +4922,45 @@ public static ReadOnlySpan MustHaveLength(this ReadOnlySpan parameter,
return parameter;
}
+ ///
+ /// Ensures that the immutable array has the specified length, or otherwise throws an .
+ ///
+ /// The immutable array to be checked.
+ /// The length that the immutable array must have.
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when does not have the specified length.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveLength(this ImmutableArray parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ var actualLength = parameter.IsDefault ? 0 : parameter.Length;
+ if (actualLength != length)
+ {
+ Throw.InvalidImmutableArrayLength(parameter, length, parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the immutable array has the specified length, or otherwise throws your custom exception.
+ ///
+ /// The immutable array to be checked.
+ /// The length that the immutable array must have.
+ /// The delegate that creates your custom exception. and are passed to this delegate.
+ /// Your custom exception thrown when does not have the specified length.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustHaveLength(this ImmutableArray parameter, int length, Func, int, Exception> exceptionFactory)
+ {
+ var actualLength = parameter.IsDefault ? 0 : parameter.Length;
+ if (actualLength != length)
+ {
+ Throw.CustomException(exceptionFactory, parameter, length);
+ }
+
+ return parameter;
+ }
+
///
/// Checks if the specified type derives from the other type. Internally, this method uses
/// by default so that constructed generic types and their corresponding generic type definitions are regarded as equal.
@@ -5329,6 +5570,43 @@ public static string MustContain([NotNull][ValidatedNotNull] this string? parame
return parameter;
}
+ ///
+ /// Ensures that the immutable array contains the specified item, or otherwise throws a .
+ ///
+ /// The immutable array to be checked.
+ /// The item that must be part of the immutable array.
+ /// The name of the parameter (optional).
+ /// The message that will be passed to the resulting exception (optional).
+ /// Thrown when does not contain .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustContain(this ImmutableArray parameter, T item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ if (!parameter.Contains(item))
+ {
+ Throw.MissingItem(parameter, item, parameterName, message);
+ }
+
+ return parameter;
+ }
+
+ ///
+ /// Ensures that the immutable array contains the specified item, or otherwise throws your custom exception.
+ ///
+ /// The immutable array to be checked.
+ /// The item that must be part of the immutable array.
+ /// The delegate that creates your custom exception. and are passed to this delegate.
+ /// Your custom exception thrown when does not contain .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ImmutableArray MustContain(this ImmutableArray parameter, T item, Func, T, Exception> exceptionFactory)
+ {
+ if (!parameter.Contains(item))
+ {
+ Throw.CustomException(exceptionFactory, parameter, item);
+ }
+
+ return parameter;
+ }
+
///
/// Ensures that the specified is not less than the given value, or otherwise throws an .
///
@@ -6634,6 +6912,17 @@ internal static class Throw
[ContractAnnotation("=> halt")]
[DoesNotReturn]
public static void EmptyString(string? parameterName = null, string? message = null) => throw new EmptyStringException(parameterName, message ?? $"{parameterName ?? "The string"} must not be an empty string, but it actually is.");
+ ///
+ /// Throws the default indicating that an has less than a
+ /// minimum number of items, using the optional parameter name and message.
+ ///
+ [ContractAnnotation("=> halt")]
+ [DoesNotReturn]
+ public static void InvalidMinimumImmutableArrayLength(ImmutableArray parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ throw new InvalidCollectionCountException(parameterName, message ?? $"{parameterName ?? "The immutable array"} must have at least a length of {length}, but it actually {(parameter.IsDefault ? "has no length because it is the default instance" : $"has a length of {parameter.Length}")}.");
+ }
+
///
/// Throws the default indicating that a comparable value must not be
/// less than or equal to the given boundary value, using the optional parameter name and message.
@@ -7144,6 +7433,18 @@ public static void MustNotBeGreaterThanOrEqualTo(T parameter, T boundary, [Ca
[ContractAnnotation("=> halt")]
[DoesNotReturn]
public static void StringDoesNotMatch(string parameter, Regex regex, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new StringDoesNotMatchException(parameterName, message ?? $"{parameterName ?? "The string"} must match the regular expression \"{regex}\", but it actually is \"{parameter}\".");
+ ///
+ /// Throws the default indicating that an immutable array has an invalid length,
+ /// using the optional parameter name and message.
+ ///
+ [ContractAnnotation("=> halt")]
+ [DoesNotReturn]
+ public static void InvalidImmutableArrayLength(ImmutableArray parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ var actualLength = parameter.IsDefault ? 0 : parameter.Length;
+ throw new InvalidCollectionCountException(parameterName, message ?? $"{parameterName ?? "The immutable array"} must have length {length}, but it actually has length {actualLength}.");
+ }
+
///
/// Throws the default indicating that a value is not one of a specified
/// collection of items, using the optional parameter name and message.
@@ -7151,6 +7452,17 @@ public static void MustNotBeGreaterThanOrEqualTo(T parameter, T boundary, [Ca
[ContractAnnotation("=> halt")]
[DoesNotReturn]
public static void ValueNotOneOf(TItem parameter, IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new ValueIsNotOneOfException(parameterName, message ?? new StringBuilder().AppendLine($"{parameterName ?? "The value"} must be one of the following items").AppendItemsWithNewLine(items).AppendLine($"but it actually is {parameter.ToStringOrNull()}.").ToString());
+ ///
+ /// Throws the default indicating that an has more than a
+ /// maximum number of items, using the optional parameter name and message.
+ ///
+ [ContractAnnotation("=> halt")]
+ [DoesNotReturn]
+ public static void InvalidMaximumImmutableArrayLength(ImmutableArray parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null)
+ {
+ throw new InvalidCollectionCountException(parameterName, message ?? $"{parameterName ?? "The immutable array"} must have at most a length of {length}, but it actually {(parameter.IsDefault ? "has no length because it is the default instance" : $"has a length of {parameter.Length}")}.");
+ }
+
///
/// Throws the default indicating that a value must not be approximately
/// equal to another value within a specified tolerance, using the optional parameter name and message.
@@ -7209,6 +7521,13 @@ public static void MustNotBeGreaterThan(T parameter, T boundary, [CallerArgum
[DoesNotReturn]
public static void StringContains(string parameter, string substring, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new SubstringException(parameterName, message ?? $"{parameterName ?? "The string"} must not contain {substring.ToStringOrNull()} as a substring ({comparisonType}), but it actually is {parameter.ToStringOrNull()}.");
///
+ /// Throws the default indicating that an 's length is not within the
+ /// given range, using the optional parameter name and message.
+ ///
+ [ContractAnnotation("=> halt")]
+ [DoesNotReturn]
+ public static void ImmutableArrayLengthNotInRange(ImmutableArray parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => throw new ArgumentOutOfRangeException(parameterName, message ?? $"{parameterName ?? "The immutable array"} must have its length in between {range.CreateRangeDescriptionText("and")}, but it actually {(parameter.IsDefault ? "has no length because it is the default instance" : $"has length {parameter.Length}")}.");
+ ///
/// Throws the default indicating that a string does not start with another one,
/// using the optional parameter name and message.
///
diff --git a/README.md b/README.md
index 64c403f..d4062b7 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
**A lightweight .NET library for expressive Guard Clauses.**
[](https://github.com/feO2x/Light.GuardClauses/blob/master/LICENSE)
-[](https://www.nuget.org/packages/Light.GuardClauses/)
-[](https://github.com/feO2x/Light.GuardClauses/blob/master/Light.GuardClauses.SingleFile.cs)
+[](https://www.nuget.org/packages/Light.GuardClauses/)
+[](https://github.com/feO2x/Light.GuardClauses/blob/master/Light.GuardClauses.SingleFile.cs)
[](https://github.com/feO2x/Light.GuardClauses/wiki)
[](https://github.com/feO2x/Light.GuardClauses/releases)
@@ -94,7 +94,7 @@ Every assertion is well-documented - explore them using IntelliSense or check ou
## Light.GuardClauses is optimized
-Since version 4, **Light.GuardClauses** is optimized for performance (measured in .NET 4.8 and .NET 6). With the incredible help of [@redknightlois](https://github.com/redknightlois) and the awesome tool [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet), most assertions are as fast as your imperative code would be.
+Since version 4, **Light.GuardClauses** is optimized for performance (measured in .NET 4.8 and .NET 8). With the incredible help of [@redknightlois](https://github.com/redknightlois) and the awesome tool [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet), most assertions are as fast as your imperative code would be.
**Light.GuardClauses** has support for [.NET analyzers / FxCopAnalyzers](https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) with the `ValidatedNotNullAttribute` and the `NotNullAttribute`. Analyzers will know when an assertion validated that a parameters is not null and consequently, CA1062 will not be raised.
@@ -116,7 +116,7 @@ Light.GuardClauses is available as a [NuGet package](https://www.nuget.org/packa
- **dotnet CLI**: `dotnet add package Light.GuardClauses`
- **Visual Studio Package Manager Console**: `Install-Package Light.GuardClauses`
-- **Package Reference in csproj**: ``
+- **Package Reference in csproj**: ``
Also, you can incorporate Light.GuardClauses as a **single source file** where the API is changed to `internal`. This is especially interesting for framework / library developers that do not want to have a dependency on the Light.GuardClauses DLL. You can grab the default .NET Standard 2.0 version in [Light.GuardClauses.SingleFile.cs](https://github.com/feO2x/Light.GuardClauses/blob/master/Light.GuardClauses.SingleFile.cs) or you can use the [Light.GuardClauses.SourceCodeTransformation](https://github.com/feO2x/Light.GuardClauses/tree/master/Code/Light.GuardClauses.SourceCodeTransformation) project to create your custom file. You can learn more about it [here](https://github.com/feO2x/Light.GuardClauses/wiki/Including-Light.GuardClauses-as-source-code).