diff --git a/Code/Light.GuardClauses.AllProjects.sln.DotSettings b/Code/Light.GuardClauses.AllProjects.sln.DotSettings index 2c4519b..aceafc4 100644 --- a/Code/Light.GuardClauses.AllProjects.sln.DotSettings +++ b/Code/Light.GuardClauses.AllProjects.sln.DotSettings @@ -2,16 +2,32 @@ True None False + WARNING + WARNING + DO_NOT_SHOW HINT HINT + WARNING HINT WARNING + True <?xml version="1.0" encoding="utf-16"?><Profile name="Kenny's Kleanup"><CSReorderTypeMembers>True</CSReorderTypeMembers><CSUpdateFileHeader>True</CSUpdateFileHeader><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CppReformatCode>True</CppReformatCode><XMLReformatCode>True</XMLReformatCode><CssReformatCode>True</CssReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" ArrangeVarStyle="False" /><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><RemoveCodeRedundancies>True</RemoveCodeRedundancies><HtmlReformatCode>True</HtmlReformatCode><JsInsertSemicolon>True</JsInsertSemicolon><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor></Profile> - C# Cleanup - Kenny's Kleanup + Kenny's Kleanup + Built-in: Full Cleanup + False + Required + Required + Required + Required + ExpressionBody + ExpressionBody + ExpressionBody + True + False True True + True True @@ -22,23 +38,64 @@ True True True + True TOGETHER_SAME_LINE + NO_INDENT True True + True + True + False True + True + False + True + 1 + 3 + COMPACT True + True True True NEVER - NEVER - NEVER - NEVER + + + + NEVER + False + ALWAYS + IF_OWNER_IS_SINGLE_LINE + NEVER DO_NOT_CHANGE + True + True True - 500 - False + False + True + True + CHOP_IF_LONG + CHOP_IF_LONG + False + True + True + True + True + True + False + CHOP_IF_LONG + CHOP_IF_LONG + CHOP_IF_LONG + + + CHOP_IF_LONG + CHOP_ALWAYS + CHOP_IF_LONG RemoveIndent RemoveIndent + False + ByFirstAttr + 150 + False False False False @@ -192,16 +249,21 @@ </TypePattern> </Patterns> False + False False True Replace Replace False + True True False False True False + False + True + False <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> @@ -256,12 +318,4 @@ True True True - True - True - True - True - True - True - True - True - True \ No newline at end of file + True \ No newline at end of file diff --git a/Code/Light.GuardClauses.sln.DotSettings b/Code/Light.GuardClauses.sln.DotSettings index 47d8c24..aceafc4 100644 --- a/Code/Light.GuardClauses.sln.DotSettings +++ b/Code/Light.GuardClauses.sln.DotSettings @@ -2,16 +2,32 @@ True None False + WARNING + WARNING + DO_NOT_SHOW HINT HINT + WARNING HINT WARNING + True <?xml version="1.0" encoding="utf-16"?><Profile name="Kenny's Kleanup"><CSReorderTypeMembers>True</CSReorderTypeMembers><CSUpdateFileHeader>True</CSUpdateFileHeader><CSEnforceVarKeywordUsageSettings>True</CSEnforceVarKeywordUsageSettings><CSMakeFieldReadonly>True</CSMakeFieldReadonly><CSArrangeQualifiers>True</CSArrangeQualifiers><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CppReformatCode>True</CppReformatCode><XMLReformatCode>True</XMLReformatCode><CssReformatCode>True</CssReformatCode><CSCodeStyleAttributes ArrangeTypeAccessModifier="True" ArrangeTypeMemberAccessModifier="True" SortModifiers="True" RemoveRedundantParentheses="False" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" ArrangeCodeBodyStyle="False" ArrangeVarStyle="False" /><CSMakeAutoPropertyGetOnly>True</CSMakeAutoPropertyGetOnly><RemoveCodeRedundancies>True</RemoveCodeRedundancies><HtmlReformatCode>True</HtmlReformatCode><JsInsertSemicolon>True</JsInsertSemicolon><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><JsReformatCode>True</JsReformatCode><JsFormatDocComments>True</JsFormatDocComments><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor></Profile> - C# Cleanup - Kenny's Kleanup + Kenny's Kleanup + Built-in: Full Cleanup + False + Required + Required + Required + Required + ExpressionBody + ExpressionBody + ExpressionBody + True + False True True + True True @@ -22,23 +38,64 @@ True True True + True TOGETHER_SAME_LINE + NO_INDENT True True + True + True + False True + True + False + True + 1 + 3 + COMPACT True + True True True NEVER - NEVER - NEVER - NEVER + + + + NEVER + False + ALWAYS + IF_OWNER_IS_SINGLE_LINE + NEVER DO_NOT_CHANGE + True + True True - 500 - False + False + True + True + CHOP_IF_LONG + CHOP_IF_LONG + False + True + True + True + True + True + False + CHOP_IF_LONG + CHOP_IF_LONG + CHOP_IF_LONG + + + CHOP_IF_LONG + CHOP_ALWAYS + CHOP_IF_LONG RemoveIndent RemoveIndent + False + ByFirstAttr + 150 + False False False False @@ -192,16 +249,21 @@ </TypePattern> </Patterns> False + False False True Replace Replace False + True True False False True False + False + True + False <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> @@ -255,4 +317,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/Code/Light.GuardClauses/CallerArgumentExpressionAttribute.cs b/Code/Light.GuardClauses/CallerArgumentExpressionAttribute.cs index 36a1f72..f5df610 100644 --- a/Code/Light.GuardClauses/CallerArgumentExpressionAttribute.cs +++ b/Code/Light.GuardClauses/CallerArgumentExpressionAttribute.cs @@ -2,14 +2,12 @@ // ReSharper disable once CheckNamespace -- CallerArgumentExpression must be in exactly this namespace namespace System.Runtime.CompilerServices; -[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] +[AttributeUsage(AttributeTargets.Parameter)] internal sealed class CallerArgumentExpressionAttribute : Attribute { - public CallerArgumentExpressionAttribute(string parameterName) - { + public CallerArgumentExpressionAttribute(string parameterName) => ParameterName = parameterName; - } public string ParameterName { get; } } -#endif \ No newline at end of file +#endif diff --git a/Code/Light.GuardClauses/Check.CommonAssertions.cs b/Code/Light.GuardClauses/Check.CommonAssertions.cs deleted file mode 100644 index 0104f58..0000000 --- a/Code/Light.GuardClauses/Check.CommonAssertions.cs +++ /dev/null @@ -1,714 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; -using Light.GuardClauses.Exceptions; -using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -namespace Light.GuardClauses; - -/// -/// The class provides access to all assertions of Light.GuardClauses. -/// -public static partial class Check -{ - /// - /// Ensures that the specified object reference is not null, or otherwise throws an . - /// - /// The object reference to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : class - { - if (parameter is null) - Throw.ArgumentNull(parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified object reference is not null, or otherwise throws your custom exception. - /// - /// The reference to be checked. - /// The delegate that creates your custom exception. - /// Your custom exception thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeNull([NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : class - { - if (parameter is null) - Throw.CustomException(exceptionFactory); - return parameter; - } - - /// - /// Ensures that the specified parameter is not the default value, or otherwise throws an - /// for reference types, or an for value types. - /// - /// The value to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is a reference type and null. - /// Thrown when is a value type and the default value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (default(T) is null) - { - if (parameter is null) - Throw.ArgumentNull(parameterName, message); - return parameter; - } - - if (EqualityComparer.Default.Equals(parameter, default!)) - Throw.ArgumentDefault(parameterName, message); - - // If we end up here, we have a value type which cannot be null -#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - return parameter; -#pragma warning restore CS8777 - } - - /// - /// Ensures that the specified parameter is not the default value, or otherwise throws your custom exception. - /// - /// The value to be checked. - /// The delegate that creates your custom exception. - /// Your custom exception thrown when is the default value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeDefault([NotNull, ValidatedNotNull] this T parameter, Func exceptionFactory) - { - if (default(T) is null) - { - if (parameter is null) - Throw.CustomException(exceptionFactory); - return parameter; - } - - if (EqualityComparer.Default.Equals(parameter, default!)) - Throw.CustomException(exceptionFactory); - - // If we end up here, we have a value type which cannot be null -#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - return parameter; -#pragma warning restore CS8777 - - } - - /// - /// 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, - /// use by default. - /// - /// The value to be checked for null. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is a reference type and is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumeration] this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (default(T) != null) - { - // If we end up here, parameter cannot be null -#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - return parameter; -#pragma warning restore CS8777 // Parameter must have a non-null value when exiting. - } - - if (parameter is null) - Throw.ArgumentNull(parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified parameter is not null when is a reference type, or otherwise - /// throws your custom exception. PLEASE NOTICE: you should only use this assertion in generic contexts, - /// use by default. - /// - /// The value to be checked for null. - /// The delegate that creates your custom exception. - /// Your custom exception thrown when is a reference type and is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeNullReference([NotNull, ValidatedNotNull, NoEnumeration] this T parameter, Func exceptionFactory) - { - if (default(T) != null) - { - // If we end up here, parameter cannot be null -#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. - return parameter; -#pragma warning restore CS8777 // Parameter must have a non-null value when exiting. - } - - if (parameter is null) - Throw.CustomException(exceptionFactory); - return parameter; - } - - /// - /// Ensures that can be cast to and returns the cast value, or otherwise throws a . - /// - /// The value to be cast. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when cannot be cast to . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message) is T castValue) - return castValue; - - Throw.InvalidTypeCast(parameter, typeof(T), parameterName, message); - return default; - } - - /// - /// Ensures that can be cast to and returns the cast value, or otherwise throws your custom exception. - /// - /// The value to be cast. - /// The delegate that creates your custom exception. The is passed to this delegate. - /// Your custom exception thrown when cannot be cast to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, Func exceptionFactory) - { - if (parameter is T castValue) - return castValue; - - Throw.CustomException(exceptionFactory, parameter); - return default; - } - - /// - /// Checks if the specified value is a valid enum value of its type. This is true when the specified value - /// is one of the constants defined in the enum, or a valid flags combination when the enum type is marked - /// with the . - /// - /// The type of the enum. - /// The enum value to be checked. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsValidEnumValue(this T parameter) where T : struct, Enum - => EnumInfo.IsValidEnumValue(parameter); - - /// - /// Ensures that the specified enum value is valid, or otherwise throws an . An enum value - /// is valid when the specified value is one of the constants defined in the enum, or a valid flags combination when the enum type - /// is marked with the . - /// - /// The type of the enum. - /// The value to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is no valid enum value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustBeValidEnumValue(this T parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : struct, Enum - { - if (!EnumInfo.IsValidEnumValue(parameter)) - Throw.EnumValueNotDefined(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified enum value is valid, or otherwise throws your custom exception. An enum value - /// is valid when the specified value is one of the constants defined in the enum, or a valid flags combination when the enum type - /// is marked with the . - /// - /// The type of the enum. - /// The value to be checked. - /// The delegate that creates your custom exception. The is passed to this delegate. - /// Your custom exception thrown when is no valid enum value, or when is no enum type. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static T MustBeValidEnumValue(this T parameter, Func exceptionFactory) where T : struct, Enum - { - if (!EnumInfo.IsValidEnumValue(parameter)) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Checks if the specified GUID is an empty one. - /// - /// The GUID to be checked. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsEmpty(this Guid parameter) => parameter == Guid.Empty; - - /// - /// Ensures that the specified GUID is not empty, or otherwise throws an . - /// - /// The GUID to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is an empty GUID. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Guid MustNotBeEmpty(this Guid parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter == Guid.Empty) - Throw.EmptyGuid(parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified GUID is not empty, or otherwise throws your custom exception. - /// - /// The GUID to be checked. - /// The delegate that creates your custom exception. - /// Your custom exception thrown when is an empty GUID. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static Guid MustNotBeEmpty(this Guid parameter, Func exceptionFactory) - { - if (parameter == Guid.Empty) - Throw.CustomException(exceptionFactory); - return parameter; - } - - /// - /// Checks if the specified is true and throws an in this case. - /// - /// The condition to be checked. The exception is thrown when it is true. - /// The message that will be passed to the (optional). - /// Thrown when is true. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvalidOperation(bool condition, string? message = null) - { - if (condition) - Throw.InvalidOperation(message); - } - - /// - /// Checks if the specified is true and throws an in this case. - /// - /// The condition to be checked. The exception is thrown when it is true. - /// The message that will be passed to the . - /// Thrown when is true. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvalidState(bool condition, string? message = null) - { - if (condition) - Throw.InvalidState(message); - } - - /// - /// Checks if the specified is true and throws an in this case. - /// - /// The condition to be checked. The exception is thrown when it is true. - /// The name of the parameter (optional). - /// The message that will be passed to the (optional). - /// Thrown when is true. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void InvalidArgument(bool condition, string? parameterName = null, string? message = null) - { - if (condition) - Throw.Argument(parameterName, message); - } - - /// - /// Checks if the specified is true and throws your custom exception in this case. - /// - /// The condition to be checked. The exception is thrown when it is true. - /// The delegate that creates your custom exception. - /// Your custom exception thrown when is true. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static void InvalidArgument(bool condition, Func exceptionFactory) - { - if (condition) - Throw.CustomException(exceptionFactory); - } - - /// - /// Checks if the specified is true and throws your custom exception in this case. - /// - /// The condition to be checked. The exception is thrown when it is true. - /// The value that is checked in the . This value is passed to the . - /// The delegate that creates your custom exception. The is passed to this delegate. - /// Your custom exception thrown when is true. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static void InvalidArgument(bool condition, T parameter, Func exceptionFactory) - { - if (condition) - Throw.CustomException(exceptionFactory, parameter); - } - - /// - /// Ensures that the specified nullable has a value and returns it, or otherwise throws a . - /// - /// The nullable to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has no value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustHaveValue([NotNull, NoEnumeration] this T? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : struct - { - if (!parameter.HasValue) - Throw.NullableHasNoValue(parameterName, message); - - return parameter.Value; - } - - /// - /// Ensures that the specified nullable has a value and returns it, or otherwise throws your custom exception. - /// - /// The nullable to be checked. - /// The delegate that creates your custom exception. - /// Thrown when has no value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static T MustHaveValue([NotNull, NoEnumeration] this T? parameter, Func exceptionFactory) where T : struct - { - if (!parameter.HasValue) - Throw.CustomException(exceptionFactory); - - return parameter.Value; - } - - /// - /// Checks if and point to the same object. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - // ReSharper disable StringLiteralTypo - [ContractAnnotation("parameter:notNull => true, other:notnull; parameter:notNull => false, other:canbenull; other:notnull => true, parameter:notnull; other:notnull => false, parameter:canbenull")] - // ReSharper restore StringLiteralTypo - public static bool IsSameAs([NoEnumeration] this T? parameter, [NoEnumeration] T? other) where T : class => - ReferenceEquals(parameter, other); - - /// - /// Ensures that and do not point to the same object instance, or otherwise - /// throws a . - /// - /// The first reference to be checked. - /// The second reference to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when both and point to the same object. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T? MustNotBeSameAs([NoEnumeration] this T? parameter, [NoEnumeration] T? other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : class - { - if (ReferenceEquals(parameter, other)) - Throw.SameObjectReference(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that and do not point to the same object instance, or otherwise - /// throws your custom exception. - /// - /// The first reference to be checked. - /// The second reference to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Thrown when both and point to the same object. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T? MustNotBeSameAs([NoEnumeration] this T? parameter, T? other, Func exceptionFactory) where T : class - { - if (ReferenceEquals(parameter, other)) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that is equal to using the default equality comparer, or otherwise throws a . - /// - /// The first value to be compared. - /// The other value to be compared. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when and are not equal. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustBe(this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!EqualityComparer.Default.Equals(parameter, other)) - Throw.ValuesNotEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that is equal to using the default equality comparer, or otherwise throws your custom exception. - /// - /// The first value to be compared. - /// The other value to be compared. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when and are not equal. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustBe(this T parameter, T other, Func exceptionFactory) - { - if (!EqualityComparer.Default.Equals(parameter, other)) - Throw.CustomException(exceptionFactory, parameter, other); - return parameter; - } - - /// - /// Ensures that is equal to using the specified equality comparer, or otherwise throws a . - /// - /// The first value to be compared. - /// The other value to be compared. - /// The equality comparer used for comparing the two values. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when and are not equal. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("equalityComparer:null => halt")] - public static T MustBe(this T parameter, T other, IEqualityComparer equalityComparer, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!equalityComparer.MustNotBeNull(nameof(equalityComparer), message).Equals(parameter, other)) - Throw.ValuesNotEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that is equal to using the specified equality comparer, or otherwise throws your custom exception. - /// - /// The first value to be compared. - /// The other value to be compared. - /// The equality comparer used for comparing the two values. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// Your custom exception thrown when and are not equal, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("equalityComparer:null => halt")] - public static T MustBe(this T parameter, T other, IEqualityComparer equalityComparer, Func, Exception> exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (equalityComparer is null || !equalityComparer.Equals(parameter, other)) - Throw.CustomException(exceptionFactory, parameter, other, equalityComparer!); - return parameter; - } - - /// - /// Ensures that is not equal to using the default equality comparer, or otherwise throws a . - /// - /// The first value to be compared. - /// The other value to be compared. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when and are equal. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustNotBe(this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (EqualityComparer.Default.Equals(parameter, other)) - Throw.ValuesEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that is not equal to using the default equality comparer, or otherwise throws your custom exception. - /// - /// The first value to be compared. - /// The other value to be compared. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when and are equal. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T MustNotBe(this T parameter, T other, Func exceptionFactory) - { - if (EqualityComparer.Default.Equals(parameter, other)) - Throw.CustomException(exceptionFactory, parameter, other); - return parameter; - } - - /// - /// Ensures that is not equal to using the specified equality comparer, or otherwise throws a . - /// - /// The first value to be compared. - /// The other value to be compared. - /// The equality comparer used for comparing the two values. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when and are equal. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("equalityComparer:null => halt")] - public static T MustNotBe(this T parameter, T other, IEqualityComparer equalityComparer, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (equalityComparer.MustNotBeNull(nameof(equalityComparer), message).Equals(parameter, other)) - Throw.ValuesEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that is not equal to using the specified equality comparer, or otherwise throws your custom exception. - /// - /// The first value to be compared. - /// The other value to be compared. - /// The equality comparer used for comparing the two values. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// Your custom exception thrown when and are equal, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("equalityComparer:null => halt")] - public static T MustNotBe(this T parameter, T other, IEqualityComparer equalityComparer, Func, Exception> exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (equalityComparer is null || equalityComparer.Equals(parameter, other)) - Throw.CustomException(exceptionFactory, parameter, other, equalityComparer!); - return parameter; - } - - /// - /// Checks if the specified value is approximately the same as the other value, using the given tolerance. - /// - /// The first value to be compared. - /// The second value to be compared. - /// The tolerance indicating how much the two values may differ from each other. - /// - /// True if and are equal or if their absolute difference - /// is smaller than the given , otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsApproximately(this double value, double other, double tolerance) => - Math.Abs(value - other) < tolerance; - - /// - /// Checks if the specified value is approximately the same as the other value, using the default tolerance of 0.0001. - /// - /// The first value to be compared. - /// The second value to be compared. - /// - /// True if and are equal or if their absolute difference - /// is smaller than 0.0001, otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsApproximately(this double value, double other) => - Math.Abs(value - other) < 0.0001; - - /// - /// Checks if the specified value is approximately the same as the other value, using the given tolerance. - /// - /// The first value to compare. - /// The second value to compare. - /// The tolerance indicating how much the two values may differ from each other. - /// - /// True if and are equal or if their absolute difference - /// is smaller than the given , otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsApproximately(this float value, float other, float tolerance) => - Math.Abs(value - other) < tolerance; - - /// - /// Checks if the specified value is approximately the same as the other value, using the default tolerance of 0.0001f. - /// - /// The first value to be compared. - /// The second value to be compared. - /// - /// True if and are equal or if their absolute difference - /// is smaller than 0.0001f, otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsApproximately(this float value, float other) => - Math.Abs(value - other) < 0.0001f; - - /// - /// Checks if the specified value is greater than or approximately the same as the other value, using the given tolerance. - /// - /// The first value to compare. - /// The second value to compare. - /// The tolerance indicating how much the two values may differ from each other. - /// - /// True if is greater than or if their absolute difference - /// is smaller than the given , otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsGreaterThanOrApproximately(this double value, double other, double tolerance) => - value > other || value.IsApproximately(other, tolerance); - - /// - /// Checks if the specified value is greater than or approximately the same as the other value, using the default tolerance of 0.0001. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// True if is greater than or if their absolute difference - /// is smaller than 0.0001, otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsGreaterThanOrApproximately(this double value, double other) => - value > other || value.IsApproximately(other); - - /// - /// Checks if the specified value is greater than or approximately the same as the other value, using the given tolerance. - /// - /// The first value to compare. - /// The second value to compare. - /// The tolerance indicating how much the two values may differ from each other. - /// - /// True if is greater than or if their absolute difference - /// is smaller than the given , otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsGreaterThanOrApproximately(this float value, float other, float tolerance) => - value > other || value.IsApproximately(other, tolerance); - - /// - /// Checks if the specified value is greater than or approximately the same as the other value, using the default tolerance of 0.0001f. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// True if is greater than or if their absolute difference - /// is smaller than 0.0001, otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsGreaterThanOrApproximately(this float value, float other) => - value > other || value.IsApproximately(other); - - /// - /// Checks if the specified value is less than or approximately the same as the other value, using the given tolerance. - /// - /// The first value to compare. - /// The second value to compare. - /// The tolerance indicating how much the two values may differ from each other. - /// - /// True if is less than or if their absolute difference - /// is smaller than the given , otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsLessThanOrApproximately(this double value, double other, double tolerance) => - value < other || value.IsApproximately(other, tolerance); - - /// - /// Checks if the specified value is less than or approximately the same as the other value, using the default tolerance of 0.0001. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// True if is less than or if their absolute difference - /// is smaller than 0.0001, otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsLessThanOrApproximately(this double value, double other) => - value < other || value.IsApproximately(other); - - /// - /// Checks if the specified value is less than or approximately the same as the other value, using the given tolerance. - /// - /// The first value to compare. - /// The second value to compare. - /// The tolerance indicating how much the two values may differ from each other. - /// - /// True if is less than or if their absolute difference - /// is smaller than the given , otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsLessThanOrApproximately(this float value, float other, float tolerance) => - value < other || value.IsApproximately(other, tolerance); - - /// - /// Checks if the specified value is less than or approximately the same as the other value, using the default tolerance of 0.0001f. - /// - /// The first value to compare. - /// The second value to compare. - /// - /// True if is less than or if their absolute difference - /// is smaller than 0.0001f, otherwise false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsLessThanOrApproximately(this float value, float other) => - value < other || value.IsApproximately(other); -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.ComparableAssertions.cs b/Code/Light.GuardClauses/Check.ComparableAssertions.cs deleted file mode 100644 index 0eb9020..0000000 --- a/Code/Light.GuardClauses/Check.ComparableAssertions.cs +++ /dev/null @@ -1,411 +0,0 @@ -using System; -using JetBrains.Annotations; -using System.Runtime.CompilerServices; -using Light.GuardClauses.Exceptions; -using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -namespace Light.GuardClauses; - -public static partial class Check -{ - /* - * ------------------------------------- - * Must Not Be Less Than - * Must Be Greater Than or Equal To - * ------------------------------------- - */ - /// - /// Ensures that the specified is not less than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be less than or equal to . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is less than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) < 0) - Throw.MustNotBeLessThan(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is not less than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be less than or equal to . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is less than , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs off - if (parameter is null || parameter.CompareTo(other) < 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /// - /// Ensures that the specified is not less than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be less than or equal to . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is less than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) < 0) - Throw.MustBeGreaterThanOrEqualTo(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is not less than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be less than or equal to . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is less than , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) < 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /* - * ------------------------------------- - * Must Be Less Than - * Must Not Be Greater Than or Equal To - * ------------------------------------- - */ - /// - /// Ensures that the specified is less than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be greater than . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is not less than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) >= 0) - Throw.MustBeLessThan(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is less than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be greater than . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is not less than , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeLessThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) >= 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /// - /// Ensures that the specified is less than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be greater than . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is not less than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) >= 0) - Throw.MustNotBeGreaterThanOrEqualTo(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is less than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be greater than . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is not less than , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeGreaterThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) >= 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /* - * ------------------------------------- - * Must Be Greater Than - * Must Not Be Less Than or Equal To - * ------------------------------------- - */ - /// - /// Ensures that the specified is greater than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be less than . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is less than or equal to . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) <= 0) - Throw.MustBeGreaterThan(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is greater than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be less than . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is less than or equal to , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) <= 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /// - /// Ensures that the specified is greater than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be less than . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is less than or equal to . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) <= 0) - Throw.MustNotBeLessThanOrEqualTo(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is greater than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be less than . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is less than or equal to , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) <= 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /* - * ------------------------------------- - * Must Not Be Greater Than - * Must Be Less Than or Equal To - * ------------------------------------- - */ - /// - /// Ensures that the specified is not greater than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be greater than or equal to . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is greater than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) > 0) - Throw.MustNotBeGreaterThan(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is not greater than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be greater than or equal to . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is greater than , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) > 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /// - /// Ensures that the specified is not greater than the given value, or otherwise throws an . - /// - /// The comparable to be checked. - /// The boundary value that must be greater than or equal to . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the specified is greater than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) > 0) - Throw.MustBeLessThanOrEqualTo(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified is not greater than the given value, or otherwise throws your custom exception. - /// - /// The comparable to be checked. - /// The boundary value that must be greater than or equal to . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when the specified is greater than , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeLessThanOrEqualTo([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || parameter.CompareTo(other) > 0) - Throw.CustomException(exceptionFactory, parameter!, other); - return parameter; - } - - /* - * ------------------------------------- - * Ranges - * ------------------------------------- - */ - /// - /// Checks if the value is within the specified range. - /// - /// The comparable to be checked. - /// The range where must be in-between. - /// True if the parameter is within the specified range, else false. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsIn([NotNull, ValidatedNotNull] this T parameter, Range range) where T : IComparable => range.IsValueWithinRange(parameter); - - /// - /// Checks if the value is not within the specified range. - /// - /// The comparable to be checked. - /// The range where must not be in-between. - /// True if the parameter is not within the specified range, else false. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsNotIn([NotNull, ValidatedNotNull] this T parameter, Range range) where T : IComparable => !range.IsValueWithinRange(parameter); - - /// - /// Ensures that is within the specified range, or otherwise throws an . - /// - /// The type of the parameter to be checked. - /// The parameter to be checked. - /// The range where must be in-between. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is not within . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (!range.IsValueWithinRange(parameter.MustNotBeNullReference(parameterName, message))) - Throw.MustBeInRange(parameter, range, parameterName, message); - return parameter; - } - - /// - /// Ensures that is within the specified range, or otherwise throws your custom exception. - /// - /// The parameter to be checked. - /// The range where must be in-between. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is not within , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, Func, Exception> exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || !range.IsValueWithinRange(parameter)) - Throw.CustomException(exceptionFactory, parameter!, range); - return parameter; - } - - /// - /// Ensures that is not within the specified range, or otherwise throws an . - /// - /// The type of the parameter to be checked. - /// The parameter to be checked. - /// The range where must not be in-between. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is within . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static T MustNotBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable - { - if (range.IsValueWithinRange(parameter.MustNotBeNullReference(parameterName, message))) - Throw.MustNotBeInRange(parameter, range, parameterName, message); - return parameter; - } - - /// - /// Ensures that is not within the specified range, or otherwise throws your custom exception. - /// - /// The parameter to be checked. - /// The range where must not be in-between. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is within , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static T MustNotBeIn([NotNull, ValidatedNotNull] this T parameter, Range range, Func, Exception> exceptionFactory) where T : IComparable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || range.IsValueWithinRange(parameter)) - Throw.CustomException(exceptionFactory, parameter!, range); - return parameter; - } -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.Contains.cs b/Code/Light.GuardClauses/Check.Contains.cs new file mode 100644 index 0000000..5e5c9f2 --- /dev/null +++ b/Code/Light.GuardClauses/Check.Contains.cs @@ -0,0 +1,28 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the string contains the specified value using the given comparison type. + /// + /// The string to be checked. + /// The other string. + /// One of the enumeration values that specifies the rules for the search. + /// True if contains , else false. + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("string:null => halt; value:null => halt")] + public static bool Contains( + // ReSharper disable once RedundantNullableFlowAttribute -- Caller might have NRTs turned off + [NotNull] [ValidatedNotNull] this string @string, + string value, + StringComparison comparisonType + ) => + @string.MustNotBeNull(nameof(@string)).IndexOf(value.MustNotBeNull(nameof(value)), comparisonType) >= 0; +} diff --git a/Code/Light.GuardClauses/Check.DateTimeAssertions.cs b/Code/Light.GuardClauses/Check.DateTimeAssertions.cs deleted file mode 100644 index feee6b2..0000000 --- a/Code/Light.GuardClauses/Check.DateTimeAssertions.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using JetBrains.Annotations; -using System.Runtime.CompilerServices; -using Light.GuardClauses.Exceptions; - -namespace Light.GuardClauses; - -public static partial class Check -{ - /// - /// Ensures that the specified uses , or otherwise throws an . - /// - /// The date time to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not use . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static DateTime MustBeUtc(this DateTime parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Kind != DateTimeKind.Utc) - Throw.MustBeUtcDateTime(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified uses , or otherwise throws your custom exception. - /// - /// The date time to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when does not use . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static DateTime MustBeUtc(this DateTime parameter, Func exceptionFactory) - { - if (parameter.Kind != DateTimeKind.Utc) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the specified uses , or otherwise throws an . - /// - /// The date time to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not use . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static DateTime MustBeLocal(this DateTime parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Kind != DateTimeKind.Local) - Throw.MustBeLocalDateTime(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified uses , or otherwise throws your custom exception. - /// - /// The date time to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when does not use . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static DateTime MustBeLocal(this DateTime parameter, Func exceptionFactory) - { - if (parameter.Kind != DateTimeKind.Local) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the specified uses , or otherwise throws an . - /// - /// The date time to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not use . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static DateTime MustBeUnspecified(this DateTime parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Kind != DateTimeKind.Unspecified) - Throw.MustBeUnspecifiedDateTime(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified uses , or otherwise throws your custom exception. - /// - /// The date time to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when does not use . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("exceptionFactory:null => halt")] - public static DateTime MustBeUnspecified(this DateTime parameter, Func exceptionFactory) - { - if (parameter.Kind != DateTimeKind.Unspecified) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.DerivesFrom.cs b/Code/Light.GuardClauses/Check.DerivesFrom.cs new file mode 100644 index 0000000..8be3fd3 --- /dev/null +++ b/Code/Light.GuardClauses/Check.DerivesFrom.cs @@ -0,0 +1,76 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Collections.Generic; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// 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. + /// + /// The type info to be checked. + /// The base class that should derive from. + /// Thrown when or is null. + [ContractAnnotation("type:null => halt; baseClass:null => halt")] + public static bool DerivesFrom( + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type baseClass + ) + { + baseClass.MustNotBeNull(nameof(baseClass)); + + var currentBaseType = type.MustNotBeNull(nameof(type)).BaseType; + while (currentBaseType != null) + { + if (currentBaseType.IsEquivalentTypeTo(baseClass)) + { + return true; + } + + currentBaseType = currentBaseType.BaseType; + } + + return false; + } + + /// + /// Checks if the specified type derives from the other type. This overload uses the specified + /// to compare the types. + /// + /// The type info to be checked. + /// The base class that should derive from. + /// The equality comparer used to compare the types. + /// Thrown when , or , or is null. + [ContractAnnotation("type:null => halt; baseClass:null => halt; typeComparer:null => halt")] + public static bool DerivesFrom( + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type baseClass, + [NotNull] [ValidatedNotNull] IEqualityComparer typeComparer + ) + { + baseClass.MustNotBeNull(nameof(baseClass)); + typeComparer.MustNotBeNull(nameof(typeComparer)); + + var currentBaseType = type.MustNotBeNull(nameof(type)).BaseType; + while (currentBaseType != null) + { + if (typeComparer.Equals(currentBaseType, baseClass)) + { + return true; + } + + currentBaseType = currentBaseType.BaseType; + } + + return false; + } +} diff --git a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs b/Code/Light.GuardClauses/Check.EnumerableAssertions.cs deleted file mode 100644 index a67209b..0000000 --- a/Code/Light.GuardClauses/Check.EnumerableAssertions.cs +++ /dev/null @@ -1,661 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; -using Light.GuardClauses.Exceptions; -using Light.GuardClauses.FrameworkExtensions; -using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -namespace Light.GuardClauses; - -public static partial class Check -{ - /// - /// Ensures that the collection has the specified number of items, or otherwise throws an . - /// - /// The collection to be checked. - /// The number of items the collection 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 number of items. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable - { - if (parameter!.Count(parameterName, message) != count) - Throw.InvalidCollectionCount(parameter, count, parameterName, message); - return parameter; - } - - /// - /// Ensures that the collection has the specified number of items, or otherwise throws your custom exception. - /// - /// The collection to be checked. - /// The number of items the collection 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 number of items, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is null || parameter.Count() != count) - Throw.CustomException(exceptionFactory, parameter, count); - return parameter; - } - - /// - /// Checks if the specified collection is null or empty. - /// - /// The collection to be checked. - /// True if the collection is null or empty, else false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("=> true, collection:canbenull; => false, collection:notnull")] - public static bool IsNullOrEmpty([NotNullWhen(false)] this IEnumerable? collection) => - collection is null || collection.Count() == 0; - - /// - /// Ensures that the collection is not null or empty, or otherwise throws an . - /// - /// The collection to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has no items. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this TCollection? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable - { - if (parameter.Count(parameterName, message) == 0) - Throw.EmptyCollection(parameterName, message); - return parameter; - } - - /// - /// Ensures that the collection is not null or empty, or otherwise throws your custom exception. - /// - /// The collection to be checked. - /// The delegate that creates your custom exception. - /// Thrown when has no items, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this TCollection? parameter, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is null || parameter.Count() == 0) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the collection contains the specified item, or otherwise throws a . - /// - /// The collection to be checked. - /// The item that must be part of the collection. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable - { - if (parameter is ICollection collection) - { - if (!collection.Contains(item)) - Throw.MissingItem(parameter, item, parameterName, message); - return parameter; - } - - if (!parameter.MustNotBeNull(parameterName, message).Contains(item)) - Throw.MissingItem(parameter, item, parameterName, message); - return parameter; - } - - /// - /// Ensures that the collection contains the specified item, or otherwise throws your custom exception. - /// - /// The collection to be checked. - /// The item that must be part of the collection. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when does not contain , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is ICollection collection) - { - if (!collection.Contains(item)) - Throw.CustomException(exceptionFactory, parameter, item); - return parameter; - } - - if (parameter is null || !parameter.Contains(item)) - Throw.CustomException(exceptionFactory, parameter, item); - return parameter; - } - - /// - /// Ensures that the collection does not contain the specified item, or otherwise throws an . - /// - /// The collection to be checked. - /// The item that must not be part of the collection. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when contains . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable - { - if (parameter is ICollection collection) - { - if (collection.Contains(item)) - Throw.ExistingItem(parameter, item, parameterName, message); - return parameter; - } - - if (parameter.MustNotBeNull(parameterName, message).Contains(item)) - Throw.ExistingItem(parameter, item, parameterName, message); - return parameter; - } - - /// - /// Ensures that the collection does not contain the specified item, or otherwise throws your custom exception. - /// - /// The collection to be checked. - /// The item that must not be part of the collection. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when contains . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustNotContain([NotNull, ValidatedNotNull] this TCollection? parameter, TItem item, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is ICollection collection) - { - if (collection.Contains(item)) - Throw.CustomException(exceptionFactory, parameter, item); - return parameter; - } - - if (parameter is null || parameter.Contains(item)) - Throw.CustomException(exceptionFactory, parameter, item); - return parameter; - } - - /// - /// Checks if the given is one of the specified . - /// - /// The item to be checked. - /// The collection that might contain the . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("items:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests - public static bool IsOneOf(this TItem item, [NotNull, ValidatedNotNull] IEnumerable items) - { - if (items is ICollection collection) - return collection.Contains(item); - - if (items is string @string && item is char character) - return @string.IndexOf(character) != -1; - - return items.MustNotBeNull(nameof(items)).ContainsViaForeach(item); - } - - /// - /// Ensures that the value is one of the specified items, or otherwise throws a . - /// - /// The value to be checked. - /// The items that should contain the value. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is not equal to one of the specified . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("items:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests - public static TItem MustBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - // ReSharper disable PossibleMultipleEnumeration - if (!parameter.IsOneOf(items.MustNotBeNull(nameof(items), message))) - Throw.ValueNotOneOf(parameter, items, parameterName, message); - return parameter; - // ReSharper restore PossibleMultipleEnumeration - } - - /// - /// Ensures that the value is one of the specified items, or otherwise throws your custom exception. - /// - /// The value to be checked. - /// The items that should contain the value. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is not equal to one of the specified , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("items:null => halt")] - public static TItem MustBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] TCollection items, Func exceptionFactory) where TCollection : class, IEnumerable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (items is null || !parameter.IsOneOf(items)) - Throw.CustomException(exceptionFactory, parameter, items!); - return parameter; - } - - /// - /// Ensures that the value is not one of the specified items, or otherwise throws a . - /// - /// The value to be checked. - /// The items that must not contain the value. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is equal to one of the specified . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("items:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests - public static TItem MustNotBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] IEnumerable items, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - // ReSharper disable PossibleMultipleEnumeration - if (parameter.IsOneOf(items.MustNotBeNull(nameof(items), message))) - Throw.ValueIsOneOf(parameter, items, parameterName, message); - return parameter; - // ReSharper restore PossibleMultipleEnumeration - } - - /// - /// Ensures that the value is not one of the specified items, or otherwise throws your custom exception. - /// - /// The value to be checked. - /// The items that must not contain the value. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is equal to one of the specified , or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("items:null => halt")] - public static TItem MustNotBeOneOf(this TItem parameter, [NotNull, ValidatedNotNull] TCollection items, Func exceptionFactory) where TCollection : class, IEnumerable - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (items is null || parameter.IsOneOf(items)) - Throw.CustomException(exceptionFactory, parameter, items!); - return parameter; - } - - /// - /// Ensures that the collection has at least the specified number of items, or otherwise throws an . - /// - /// The collection to be checked. - /// The number of items the collection should have at least. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain at least the specified number of items. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMinimumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable - { - if (parameter.Count(parameterName, message) < count) - Throw.InvalidMinimumCollectionCount(parameter, count, parameterName, message); - return parameter; - } - - /// - /// Ensures that the collection has at least the specified number of items, or otherwise throws your custom exception. - /// - /// The collection to be checked. - /// The number of items the collection should have at least. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when does not contain at least the specified number of items, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMinimumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is null || parameter.Count() < count) - Throw.CustomException(exceptionFactory, parameter, count); - return parameter; - } - - /// - /// Ensures that the collection has at most the specified number of items, or otherwise throws an . - /// - /// The collection to be checked. - /// The number of items the collection should have at most. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain at most the specified number of items. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMaximumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where TCollection : class, IEnumerable - { - if (parameter.Count(parameterName, message) > count) - Throw.InvalidMaximumCollectionCount(parameter, count, parameterName, message); - return parameter; - } - - /// - /// Ensures that the collection has at most the specified number of items, or otherwise throws your custom exception. - /// - /// The collection to be checked. - /// The number of items the collection should have at most. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when does not contain at most the specified number of items, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static TCollection MustHaveMaximumCount([NotNull, ValidatedNotNull] this TCollection? parameter, int count, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is null || parameter.Count() > count) - Throw.CustomException(exceptionFactory, parameter, count); - return parameter; - } - - /// - /// Ensures that the span has the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The length that the span 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 Span MustHaveLength(this Span parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length != length) - Throw.InvalidSpanLength(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span has the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length that the span 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 Span MustHaveLength(this Span parameter, int length, SpanExceptionFactory exceptionFactory) - { - if (parameter.Length != length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span has the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length that the span must have. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Your custom exception thrown when does not have the specified length. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustHaveLength(this ReadOnlySpan parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length != length) - Throw.InvalidSpanLength(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span has the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length that the span 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 ReadOnlySpan MustHaveLength(this ReadOnlySpan parameter, int length, ReadOnlySpanExceptionFactory exceptionFactory) - { - if (parameter.Length != length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is longer than the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The value that the span must be longer than. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is shorter than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeLongerThan(this Span parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length <= length) - Throw.SpanMustBeLongerThan(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is longer than the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length value that the span must be longer than. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is shorter than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeLongerThan(this Span parameter, int length, SpanExceptionFactory exceptionFactory) - { - if (parameter.Length <= length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is longer than the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The value that the span must be longer than. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is shorter than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeLongerThan(this ReadOnlySpan parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length <= length) - Throw.SpanMustBeLongerThan(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is longer than the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length value that the span must be longer than. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is shorter than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeLongerThan(this ReadOnlySpan parameter, int length, ReadOnlySpanExceptionFactory exceptionFactory) - { - if (parameter.Length <= length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is longer than or equal to the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The value that the span must be longer than or equal to. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is shorter than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeLongerThanOrEqualTo(this Span parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length < length) - Throw.SpanMustBeLongerThanOrEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is longer than or equal to the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The value that the span must be longer than or equal to. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is shorter than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeLongerThanOrEqualTo(this Span parameter, int length, SpanExceptionFactory exceptionFactory) - { - if (parameter.Length < length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is longer than or equal to the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The value that the span must be longer than or equal to. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is shorter than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeLongerThanOrEqualTo(this ReadOnlySpan parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length < length) - Throw.SpanMustBeLongerThanOrEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is longer than or equal to the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The value that the span must be longer than or equal to. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is shorter than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeLongerThanOrEqualTo(this ReadOnlySpan parameter, int length, ReadOnlySpanExceptionFactory exceptionFactory) - { - if (parameter.Length < length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is shorter than the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The length value that the span must be shorter than. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is longer than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeShorterThan(this Span parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length >= length) - Throw.SpanMustBeShorterThan(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is shorter than the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length value that the span must be shorter than. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is longer than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeShorterThan(this Span parameter, int length, SpanExceptionFactory exceptionFactory) - { - if (parameter.Length >= length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is shorter than the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The length value that the span must be shorter than. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is longer than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeShorterThan(this ReadOnlySpan parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length >= length) - Throw.SpanMustBeShorterThan(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is shorter than the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length value that the span must be shorter than. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is longer than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeShorterThan(this ReadOnlySpan parameter, int length, ReadOnlySpanExceptionFactory exceptionFactory) - { - if (parameter.Length >= length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The length value that the span must be shorter than or equal to. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is longer than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeShorterThanOrEqualTo(this Span parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length > length) - Throw.SpanMustBeShorterThanOrEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length value that the span must be shorter than or equal to. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is longer than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Span MustBeShorterThanOrEqualTo(this Span parameter, int length, SpanExceptionFactory exceptionFactory) - { - if (parameter.Length > length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws an . - /// - /// The span to be checked. - /// The length value that the span must be shorter than or equal to. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is longer than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeShorterThanOrEqualTo(this ReadOnlySpan parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Length > length) - Throw.SpanMustBeShorterThanOrEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws your custom exception. - /// - /// The span to be checked. - /// The length value that the span must be shorter than or equal to. - /// The delegate that creates your custom exception. and are passed to it. - /// Your custom exception thrown when is longer than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan MustBeShorterThanOrEqualTo(this ReadOnlySpan parameter, int length, ReadOnlySpanExceptionFactory exceptionFactory) - { - if (parameter.Length > length) - Throw.CustomSpanException(exceptionFactory, parameter, length); - return parameter; - } -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.Equals.cs b/Code/Light.GuardClauses/Check.Equals.cs new file mode 100644 index 0000000..688e191 --- /dev/null +++ b/Code/Light.GuardClauses/Check.Equals.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.CompilerServices; +using Light.GuardClauses.Exceptions; +using Light.GuardClauses.FrameworkExtensions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified strings are equal, using the given comparison rules. + /// + /// The first string to compare. + /// The second string to compare. + /// One of the enumeration values that specifies the rules for the comparison. + /// True if the two strings are considered equal, else false. + /// Thrown when is no valid enum value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool Equals(this string? @string, string? value, StringComparisonType comparisonType) + { + if ((int) comparisonType < 6) + { + return string.Equals(@string, value, (StringComparison) comparisonType); + } + + switch (comparisonType) + { + case StringComparisonType.OrdinalIgnoreWhiteSpace: + return @string.EqualsOrdinalIgnoreWhiteSpace(value); + case StringComparisonType.OrdinalIgnoreCaseIgnoreWhiteSpace: + return @string.EqualsOrdinalIgnoreCaseIgnoreWhiteSpace(value); + default: + Throw.EnumValueNotDefined(comparisonType, nameof(comparisonType)); + return false; + } + } +} diff --git a/Code/Light.GuardClauses/Check.Implements.cs b/Code/Light.GuardClauses/Check.Implements.cs new file mode 100644 index 0000000..e0643d4 --- /dev/null +++ b/Code/Light.GuardClauses/Check.Implements.cs @@ -0,0 +1,79 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Collections.Generic; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the type implements the specified interface type. Internally, this method uses + /// so that constructed generic types and their corresponding generic type definitions are regarded as equal. + /// + /// The type to be checked. + /// The interface type that should implement. + /// Thrown when or is null. + [ContractAnnotation("type:null => halt; interfaceType:null => halt")] + public static bool Implements( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type interfaceType + ) + { + type.MustNotBeNull(); + interfaceType.MustNotBeNull(); + + var implementedInterfaces = type.GetInterfaces(); + for (var i = 0; i < implementedInterfaces.Length; ++i) + { + if (interfaceType.IsEquivalentTypeTo(implementedInterfaces[i])) + { + return true; + } + } + + return false; + } + + /// + /// Checks if the type implements the specified interface type. This overload uses the specified + /// to compare the interface types. + /// + /// The type to be checked. + /// The interface type that should implement. + /// The equality comparer used to compare the interface types. + /// Thrown when , or , or is null. + [ContractAnnotation("type:null => halt; interfaceType:null => halt; typeComparer:null => halt")] + public static bool Implements( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type interfaceType, + [NotNull] [ValidatedNotNull] IEqualityComparer typeComparer + ) + { + type.MustNotBeNull(); + interfaceType.MustNotBeNull(); + typeComparer.MustNotBeNull(); + + var implementedInterfaces = type.GetInterfaces(); + for (var i = 0; i < implementedInterfaces.Length; ++i) + { + if (typeComparer.Equals(implementedInterfaces[i], interfaceType)) + { + return true; + } + } + + return false; + } +} diff --git a/Code/Light.GuardClauses/Check.InheritsFrom.cs b/Code/Light.GuardClauses/Check.InheritsFrom.cs new file mode 100644 index 0000000..6e2ad44 --- /dev/null +++ b/Code/Light.GuardClauses/Check.InheritsFrom.cs @@ -0,0 +1,61 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the given type derives from the specified base class or interface type. Internally, this method uses + /// so that constructed generic types and their corresponding generic type definitions are regarded as equal. + /// + /// The type to be checked. + /// The type describing an interface or base class that should derive from or implement. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; baseClassOrInterfaceType:null => halt")] + public static bool InheritsFrom( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type baseClassOrInterfaceType + ) => + baseClassOrInterfaceType + .MustNotBeNull(nameof(baseClassOrInterfaceType)) + .IsInterface ? + type.Implements(baseClassOrInterfaceType) : + type.DerivesFrom(baseClassOrInterfaceType); + + /// + /// Checks if the given type derives from the specified base class or interface type. This overload uses the specified + /// to compare the types. + /// + /// The type to be checked. + /// The type describing an interface or base class that should derive from or implement. + /// The equality comparer used to compare the types. + /// Thrown when , or , or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; baseClassOrInterfaceType:null => halt; typeComparer:null => halt")] + public static bool InheritsFrom( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type baseClassOrInterfaceType, + [NotNull] [ValidatedNotNull] IEqualityComparer typeComparer + ) => + baseClassOrInterfaceType + .MustNotBeNull(nameof(baseClassOrInterfaceType)) + .IsInterface ? + type.Implements(baseClassOrInterfaceType, typeComparer) : + type.DerivesFrom(baseClassOrInterfaceType, typeComparer); +} diff --git a/Code/Light.GuardClauses/Check.InvalidArgument.cs b/Code/Light.GuardClauses/Check.InvalidArgument.cs new file mode 100644 index 0000000..cc50e69 --- /dev/null +++ b/Code/Light.GuardClauses/Check.InvalidArgument.cs @@ -0,0 +1,58 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified is true and throws an in this case. + /// + /// The condition to be checked. The exception is thrown when it is true. + /// The name of the parameter (optional). + /// The message that will be passed to the (optional). + /// Thrown when is true. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InvalidArgument(bool condition, string? parameterName = null, string? message = null) + { + if (condition) + { + Throw.Argument(parameterName, message); + } + } + + /// + /// Checks if the specified is true and throws your custom exception in this case. + /// + /// The condition to be checked. The exception is thrown when it is true. + /// The delegate that creates your custom exception. + /// Your custom exception thrown when is true. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static void InvalidArgument(bool condition, Func exceptionFactory) + { + if (condition) + { + Throw.CustomException(exceptionFactory); + } + } + + /// + /// Checks if the specified is true and throws your custom exception in this case. + /// + /// The condition to be checked. The exception is thrown when it is true. + /// The value that is checked in the . This value is passed to the . + /// The delegate that creates your custom exception. The is passed to this delegate. + /// Your custom exception thrown when is true. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static void InvalidArgument(bool condition, T parameter, Func exceptionFactory) + { + if (condition) + { + Throw.CustomException(exceptionFactory, parameter); + } + } +} diff --git a/Code/Light.GuardClauses/Check.InvalidOperation.cs b/Code/Light.GuardClauses/Check.InvalidOperation.cs new file mode 100644 index 0000000..c4ff5b7 --- /dev/null +++ b/Code/Light.GuardClauses/Check.InvalidOperation.cs @@ -0,0 +1,23 @@ +using System; +using System.Runtime.CompilerServices; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified is true and throws an in this case. + /// + /// The condition to be checked. The exception is thrown when it is true. + /// The message that will be passed to the (optional). + /// Thrown when is true. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InvalidOperation(bool condition, string? message = null) + { + if (condition) + { + Throw.InvalidOperation(message); + } + } +} diff --git a/Code/Light.GuardClauses/Check.InvalidState.cs b/Code/Light.GuardClauses/Check.InvalidState.cs new file mode 100644 index 0000000..1e89445 --- /dev/null +++ b/Code/Light.GuardClauses/Check.InvalidState.cs @@ -0,0 +1,22 @@ +using System.Runtime.CompilerServices; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified is true and throws an in this case. + /// + /// The condition to be checked. The exception is thrown when it is true. + /// The message that will be passed to the . + /// Thrown when is true. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void InvalidState(bool condition, string? message = null) + { + if (condition) + { + Throw.InvalidState(message); + } + } +} diff --git a/Code/Light.GuardClauses/Check.IsApproximately.cs b/Code/Light.GuardClauses/Check.IsApproximately.cs new file mode 100644 index 0000000..698450e --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsApproximately.cs @@ -0,0 +1,61 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified value is approximately the same as the other value, using the given tolerance. + /// + /// The first value to be compared. + /// The second value to be compared. + /// The tolerance indicating how much the two values may differ from each other. + /// + /// True if and are equal or if their absolute difference + /// is smaller than the given , otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsApproximately(this double value, double other, double tolerance) => + Math.Abs(value - other) < tolerance; + + /// + /// Checks if the specified value is approximately the same as the other value, using the default tolerance of 0.0001. + /// + /// The first value to be compared. + /// The second value to be compared. + /// + /// True if and are equal or if their absolute difference + /// is smaller than 0.0001, otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsApproximately(this double value, double other) => + Math.Abs(value - other) < 0.0001; + + /// + /// Checks if the specified value is approximately the same as the other value, using the given tolerance. + /// + /// The first value to compare. + /// The second value to compare. + /// The tolerance indicating how much the two values may differ from each other. + /// + /// True if and are equal or if their absolute difference + /// is smaller than the given , otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsApproximately(this float value, float other, float tolerance) => + Math.Abs(value - other) < tolerance; + + /// + /// Checks if the specified value is approximately the same as the other value, using the default tolerance of 0.0001f. + /// + /// The first value to be compared. + /// The second value to be compared. + /// + /// True if and are equal or if their absolute difference + /// is smaller than 0.0001f, otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsApproximately(this float value, float other) => + Math.Abs(value - other) < 0.0001f; +} diff --git a/Code/Light.GuardClauses/Check.IsDigit.cs b/Code/Light.GuardClauses/Check.IsDigit.cs new file mode 100644 index 0000000..fb7756a --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsDigit.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified character is a digit. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsDigit(this char character) => char.IsDigit(character); +} diff --git a/Code/Light.GuardClauses/Check.IsEmailAddress.cs b/Code/Light.GuardClauses/Check.IsEmailAddress.cs new file mode 100644 index 0000000..7cfb698 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsEmailAddress.cs @@ -0,0 +1,31 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text.RegularExpressions; +using JetBrains.Annotations; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified string is an email address using the default email regular expression + /// defined in . + /// + /// The string to be checked if it is an email address. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("emailAddress:null => false")] + public static bool IsEmailAddress([NotNullWhen(true)] this string? emailAddress) => + emailAddress != null && RegularExpressions.EmailRegex.IsMatch(emailAddress); + + /// + /// Checks if the specified string is an email address using the provided regular expression for validation. + /// + /// The string to be checked. + /// The regular expression that determines whether the input string is an email address. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("emailAddress:null => false; emailAddressPattern:null => halt")] + public static bool IsEmailAddress([NotNullWhen(true)] this string? emailAddress, Regex emailAddressPattern) => + emailAddress != null && emailAddressPattern.MustNotBeNull(nameof(emailAddressPattern)).IsMatch(emailAddress); +} diff --git a/Code/Light.GuardClauses/Check.IsEmpty.cs b/Code/Light.GuardClauses/Check.IsEmpty.cs new file mode 100644 index 0000000..46574bb --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsEmpty.cs @@ -0,0 +1,14 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified GUID is an empty one. + /// + /// The GUID to be checked. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsEmpty(this Guid parameter) => parameter == Guid.Empty; +} diff --git a/Code/Light.GuardClauses/Check.IsEquivalentTypeTo.cs b/Code/Light.GuardClauses/Check.IsEquivalentTypeTo.cs new file mode 100644 index 0000000..585abaa --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsEquivalentTypeTo.cs @@ -0,0 +1,36 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the two specified types are equivalent. This is true when both types are equal or + /// when one type is a constructed generic type and the other type is the corresponding generic type definition. + /// + /// The first type to be checked. + /// The other type to be checked. + /// + /// True if both types are null, or if both are equal, or if one type + /// is a constructed generic type and the other one is the corresponding generic type definition, else false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsEquivalentTypeTo(this Type? type, Type? other) => + ReferenceEquals(type, other) || + (type is not null && + other is not null && + (type == other || + (type.IsConstructedGenericType != other.IsConstructedGenericType && + CheckTypeEquivalency(type, other)))); + + private static bool CheckTypeEquivalency(Type type, Type other) + { + if (type.IsConstructedGenericType) + { + return type.GetGenericTypeDefinition() == other; + } + + return other.GetGenericTypeDefinition() == type; + } +} diff --git a/Code/Light.GuardClauses/Check.IsGreaterThanOrApproximately.cs b/Code/Light.GuardClauses/Check.IsGreaterThanOrApproximately.cs new file mode 100644 index 0000000..caca671 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsGreaterThanOrApproximately.cs @@ -0,0 +1,60 @@ +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified value is greater than or approximately the same as the other value, using the given tolerance. + /// + /// The first value to compare. + /// The second value to compare. + /// The tolerance indicating how much the two values may differ from each other. + /// + /// True if is greater than or if their absolute difference + /// is smaller than the given , otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsGreaterThanOrApproximately(this double value, double other, double tolerance) => + value > other || value.IsApproximately(other, tolerance); + + /// + /// Checks if the specified value is greater than or approximately the same as the other value, using the default tolerance of 0.0001. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// True if is greater than or if their absolute difference + /// is smaller than 0.0001, otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsGreaterThanOrApproximately(this double value, double other) => + value > other || value.IsApproximately(other); + + /// + /// Checks if the specified value is greater than or approximately the same as the other value, using the given tolerance. + /// + /// The first value to compare. + /// The second value to compare. + /// The tolerance indicating how much the two values may differ from each other. + /// + /// True if is greater than or if their absolute difference + /// is smaller than the given , otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsGreaterThanOrApproximately(this float value, float other, float tolerance) => + value > other || value.IsApproximately(other, tolerance); + + /// + /// Checks if the specified value is greater than or approximately the same as the other value, using the default tolerance of 0.0001f. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// True if is greater than or if their absolute difference + /// is smaller than 0.0001, otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsGreaterThanOrApproximately(this float value, float other) => + value > other || value.IsApproximately(other); +} diff --git a/Code/Light.GuardClauses/Check.IsIn.cs b/Code/Light.GuardClauses/Check.IsIn.cs new file mode 100644 index 0000000..b33484f --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsIn.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.CompilerServices; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the value is within the specified range. + /// + /// The comparable to be checked. + /// The range where must be in-between. + /// True if the parameter is within the specified range, else false. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsIn([NotNull] [ValidatedNotNull] this T parameter, Range range) + where T : IComparable => + range.IsValueWithinRange(parameter); +} diff --git a/Code/Light.GuardClauses/Check.IsLessThanOrApproximately.cs b/Code/Light.GuardClauses/Check.IsLessThanOrApproximately.cs new file mode 100644 index 0000000..c24c1a0 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsLessThanOrApproximately.cs @@ -0,0 +1,60 @@ +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified value is less than or approximately the same as the other value, using the given tolerance. + /// + /// The first value to compare. + /// The second value to compare. + /// The tolerance indicating how much the two values may differ from each other. + /// + /// True if is less than or if their absolute difference + /// is smaller than the given , otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsLessThanOrApproximately(this double value, double other, double tolerance) => + value < other || value.IsApproximately(other, tolerance); + + /// + /// Checks if the specified value is less than or approximately the same as the other value, using the default tolerance of 0.0001. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// True if is less than or if their absolute difference + /// is smaller than 0.0001, otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsLessThanOrApproximately(this double value, double other) => + value < other || value.IsApproximately(other); + + /// + /// Checks if the specified value is less than or approximately the same as the other value, using the given tolerance. + /// + /// The first value to compare. + /// The second value to compare. + /// The tolerance indicating how much the two values may differ from each other. + /// + /// True if is less than or if their absolute difference + /// is smaller than the given , otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsLessThanOrApproximately(this float value, float other, float tolerance) => + value < other || value.IsApproximately(other, tolerance); + + /// + /// Checks if the specified value is less than or approximately the same as the other value, using the default tolerance of 0.0001f. + /// + /// The first value to compare. + /// The second value to compare. + /// + /// True if is less than or if their absolute difference + /// is smaller than 0.0001f, otherwise false. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsLessThanOrApproximately(this float value, float other) => + value < other || value.IsApproximately(other); +} diff --git a/Code/Light.GuardClauses/Check.IsLetter.cs b/Code/Light.GuardClauses/Check.IsLetter.cs new file mode 100644 index 0000000..2639fc9 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsLetter.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified character is a letter. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsLetter(this char character) => char.IsLetter(character); +} diff --git a/Code/Light.GuardClauses/Check.IsLetterOrDigit.cs b/Code/Light.GuardClauses/Check.IsLetterOrDigit.cs new file mode 100644 index 0000000..1acd030 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsLetterOrDigit.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified character is a letter or digit. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsLetterOrDigit(this char character) => char.IsLetterOrDigit(character); +} diff --git a/Code/Light.GuardClauses/Check.IsNewLine.cs b/Code/Light.GuardClauses/Check.IsNewLine.cs new file mode 100644 index 0000000..80979ba --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsNewLine.cs @@ -0,0 +1,18 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the string is either "\n" or "\r\n". This is done independently of the current value of . + /// + /// The string to be checked. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("=> false, parameter:canbenull; => true, parameter:notnull")] + public static bool IsNewLine([NotNullWhen(true)] this string? parameter) => + parameter == "\n" || parameter == "\r\n"; +} diff --git a/Code/Light.GuardClauses/Check.IsNotIn.cs b/Code/Light.GuardClauses/Check.IsNotIn.cs new file mode 100644 index 0000000..3cf76a6 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsNotIn.cs @@ -0,0 +1,20 @@ +using System; +using System.Runtime.CompilerServices; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the value is not within the specified range. + /// + /// The comparable to be checked. + /// The range where must not be in-between. + /// True if the parameter is not within the specified range, else false. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsNotIn([NotNull] [ValidatedNotNull] this T parameter, Range range) + where T : IComparable => + !range.IsValueWithinRange(parameter); +} diff --git a/Code/Light.GuardClauses/Check.IsNullOrEmpty.cs b/Code/Light.GuardClauses/Check.IsNullOrEmpty.cs new file mode 100644 index 0000000..d858001 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsNullOrEmpty.cs @@ -0,0 +1,28 @@ +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.FrameworkExtensions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified collection is null or empty. + /// + /// The collection to be checked. + /// True if the collection is null or empty, else false. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("=> true, collection:canbenull; => false, collection:notnull")] + public static bool IsNullOrEmpty([NotNullWhen(false)] this IEnumerable? collection) => + collection is null || collection.Count() == 0; + + /// + /// Checks if the specified string is null or empty. + /// + /// The string to be checked. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("=> false, string:notnull; => true, string:canbenull")] + public static bool IsNullOrEmpty([NotNullWhen(false)] this string? @string) => string.IsNullOrEmpty(@string); +} diff --git a/Code/Light.GuardClauses/Check.IsNullOrWhiteSpace.cs b/Code/Light.GuardClauses/Check.IsNullOrWhiteSpace.cs new file mode 100644 index 0000000..c67f171 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsNullOrWhiteSpace.cs @@ -0,0 +1,17 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified string is null, empty, or contains only white space. + /// + /// The string to be checked. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("=> false, string:notnull; => true, string:canbenull")] + public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? @string) => + string.IsNullOrWhiteSpace(@string); +} diff --git a/Code/Light.GuardClauses/Check.IsOneOf.cs b/Code/Light.GuardClauses/Check.IsOneOf.cs new file mode 100644 index 0000000..25b0063 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsOneOf.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.FrameworkExtensions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the given is one of the specified . + /// + /// The item to be checked. + /// The collection that might contain the . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("items:null => halt")] + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + public static bool IsOneOf(this TItem item, [NotNull] [ValidatedNotNull] IEnumerable items) + { + if (items is ICollection collection) + { + return collection.Contains(item); + } + + if (items is string @string && item is char character) + { + return @string.IndexOf(character) != -1; + } + + return items.MustNotBeNull(nameof(items)).ContainsViaForeach(item); + } +} diff --git a/Code/Light.GuardClauses/Check.IsOpenConstructedGenericType.cs b/Code/Light.GuardClauses/Check.IsOpenConstructedGenericType.cs new file mode 100644 index 0000000..7d8348e --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsOpenConstructedGenericType.cs @@ -0,0 +1,26 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the given is a generic type that has open generic parameters, + /// but is no generic type definition. + /// + /// The type to be checked. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt")] + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + public static bool IsOpenConstructedGenericType([NotNull] [ValidatedNotNull] this Type type) => + type.MustNotBeNull(nameof(type)).IsGenericType && + type.ContainsGenericParameters && + type.IsGenericTypeDefinition == false; +} diff --git a/Code/Light.GuardClauses/Check.IsOrDerivesFrom.cs b/Code/Light.GuardClauses/Check.IsOrDerivesFrom.cs new file mode 100644 index 0000000..ed74bee --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsOrDerivesFrom.cs @@ -0,0 +1,48 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the given is equal to the specified or if it derives from it. Internally, this + /// method uses so that constructed generic types and their corresponding generic type definitions are regarded as equal. + /// + /// The type to be checked. + /// The type that is equivalent to or the base class type where derives from. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; otherType:null => halt")] + public static bool IsOrDerivesFrom( + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type otherType + ) => + type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.DerivesFrom(otherType); + + /// + /// Checks if the given is equal to the specified or if it derives from it. This overload uses the specified + /// to compare the types. + /// + /// The type to be checked. + /// The type that is equivalent to or the base class type where derives from. + /// The equality comparer used to compare the types. + /// Thrown when , or , or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; otherType:null => halt; typeComparer:null => halt")] + public static bool IsOrDerivesFrom( + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type otherType, + [NotNull] [ValidatedNotNull] IEqualityComparer typeComparer + ) => + typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type, otherType.MustNotBeNull(nameof(otherType))) || + type.DerivesFrom(otherType, typeComparer); +} diff --git a/Code/Light.GuardClauses/Check.IsOrImplements.cs b/Code/Light.GuardClauses/Check.IsOrImplements.cs new file mode 100644 index 0000000..aea0e10 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsOrImplements.cs @@ -0,0 +1,58 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the given is equal to the specified or if it implements it. Internally, this + /// method uses so that constructed generic types and their corresponding generic type definitions are regarded as equal. + /// + /// The type to be checked. + /// The type that is equivalent to or the interface type that implements. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; otherType:null => halt")] + public static bool IsOrImplements( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type otherType + ) => + type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.Implements(otherType); + + /// + /// Checks if the given is equal to the specified or if it implements it. This overload uses the specified + /// to compare the types. + /// + /// , + /// The type to be checked. + /// The type that is equivalent to or the interface type that implements. + /// The equality comparer used to compare the interface types. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; otherType:null => halt")] + public static bool IsOrImplements( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type otherType, + [NotNull] [ValidatedNotNull] IEqualityComparer typeComparer + ) => + typeComparer.MustNotBeNull(nameof(typeComparer)).Equals( + type.MustNotBeNull(nameof(type)), + otherType.MustNotBeNull(nameof(otherType)) + ) || + type.Implements(otherType, typeComparer); +} diff --git a/Code/Light.GuardClauses/Check.IsOrInheritsFrom.cs b/Code/Light.GuardClauses/Check.IsOrInheritsFrom.cs new file mode 100644 index 0000000..62549f4 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsOrInheritsFrom.cs @@ -0,0 +1,56 @@ +#if NET8_0 +using System.Diagnostics.CodeAnalysis; +#endif +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the given is equal to the specified or if it derives from it or implements it. + /// Internally, this method uses so that constructed generic types and their corresponding generic type definitions + /// are regarded as equal. + /// + /// The type to be checked. + /// The type that is equivalent to or the base class type where derives from. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; otherType:null => halt")] + public static bool IsOrInheritsFrom( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type otherType + ) => + type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.InheritsFrom(otherType); + + + /// + /// Checks if the given is equal to the specified or if it derives from it or implements it. + /// This overload uses the specified to compare the types. + /// + /// The type to be checked. + /// The type that is equivalent to or the base class type where derives from. + /// The equality comparer used to compare the types. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("type:null => halt; otherType:null => halt; typeComparer:null => halt")] + public static bool IsOrInheritsFrom( +#if NET8_0 + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] +#endif + [NotNull] [ValidatedNotNull] this Type type, + [NotNull] [ValidatedNotNull] Type otherType, + [NotNull] [ValidatedNotNull] IEqualityComparer typeComparer + ) => + typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type, otherType.MustNotBeNull(nameof(otherType))) || + type.InheritsFrom(otherType, typeComparer); +} diff --git a/Code/Light.GuardClauses/Check.IsSameAs.cs b/Code/Light.GuardClauses/Check.IsSameAs.cs new file mode 100644 index 0000000..8d4c063 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsSameAs.cs @@ -0,0 +1,19 @@ +using System.Runtime.CompilerServices; +using JetBrains.Annotations; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if and point to the same object. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + // ReSharper disable StringLiteralTypo + [ContractAnnotation( + "parameter:notNull => true, other:notnull; parameter:notNull => false, other:canbenull; other:notnull => true, parameter:notnull; other:notnull => false, parameter:canbenull" + )] + // ReSharper restore StringLiteralTypo + public static bool IsSameAs([NoEnumeration] this T? parameter, [NoEnumeration] T? other) where T : class => + ReferenceEquals(parameter, other); +} diff --git a/Code/Light.GuardClauses/Check.IsSubstringOf.cs b/Code/Light.GuardClauses/Check.IsSubstringOf.cs new file mode 100644 index 0000000..7812ef2 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsSubstringOf.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the string is a substring of the other string. + /// + /// The string to be checked. + /// The other string. + /// True if is a substring of , else false. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("value:null => halt; other:null => halt")] + // ReSharper disable RedundantNullableFlowAttribute + public static bool IsSubstringOf( + [NotNull] [ValidatedNotNull] this string value, + [NotNull] [ValidatedNotNull] string other + ) => + other.MustNotBeNull(nameof(other)).Contains(value); + // ReSharper restore RedundantNullableFlowAttribute + + /// + /// Checks if the string is a substring of the other string. + /// + /// The string to be checked. + /// The other string. + /// One of the enumeration values that specifies the rules for the search. + /// True if is a substring of , else false. + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("value:null => halt; other:null => halt")] + // ReSharper disable RedundantNullableFlowAttribute + public static bool IsSubstringOf( + [NotNull] [ValidatedNotNull] this string value, + [NotNull] [ValidatedNotNull] string other, + StringComparison comparisonType + ) => + other.MustNotBeNull(nameof(other)).IndexOf(value, comparisonType) != -1; + // ReSharper disable RedundantNullableFlowAttribute +} diff --git a/Code/Light.GuardClauses/Check.IsTrimmed.cs b/Code/Light.GuardClauses/Check.IsTrimmed.cs new file mode 100644 index 0000000..727de57 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsTrimmed.cs @@ -0,0 +1,39 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified string is trimmed, i.e. it does not start or end with + /// white space characters. Inputting an empty string will return true. When null is passed, + /// you can control the return value with which will + /// return true by default. + /// + /// The string to be checked. + /// + /// The value indicating whether true or false should be returned from this method when the + /// is null. The default value is true. + /// + /// + /// True if the is trimmed, else false. An empty string will result in true. + /// You can control the return value with when the + /// is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTrimmed(this string? parameter, bool regardNullAsTrimmed = true) => + parameter is null ? regardNullAsTrimmed : parameter.AsSpan().IsTrimmed(); + + /// + /// Checks if the specified character span is trimmed, i.e. it does not start or end with + /// white space characters. Inputting an empty span will return true. + /// + /// The character span to be checked. + /// True if the is trimmed, else false. An empty span will result in true. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTrimmed(this ReadOnlySpan parameter) => + parameter.Length == 0 || + !parameter[0].IsWhiteSpace() && + !parameter[parameter.Length - 1].IsWhiteSpace(); +} diff --git a/Code/Light.GuardClauses/Check.IsTrimmedAtEnd.cs b/Code/Light.GuardClauses/Check.IsTrimmedAtEnd.cs new file mode 100644 index 0000000..644ba56 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsTrimmedAtEnd.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// 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. + /// + /// The string to be checked. + /// + /// The value indicating whether true or false should be returned from this method when the + /// is null. The default value is true. + /// + /// + /// True if the is trimmed at the end, else false. + /// An empty string will result in true. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTrimmedAtEnd(this string? parameter, bool regardNullAsTrimmed = true) => + parameter is null ? regardNullAsTrimmed : parameter.AsSpan().IsTrimmedAtEnd(); + + /// + /// Checks if the specified character span is trimmed at the end, i.e. it does not end with + /// white space characters. Inputting an empty span will return true. + /// + /// The character span to be checked. + /// + /// True if the is trimmed at the end, else false. + /// An empty span will result in true. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTrimmedAtEnd(this ReadOnlySpan parameter) => + parameter.Length == 0 || !parameter[parameter.Length - 1].IsWhiteSpace(); +} diff --git a/Code/Light.GuardClauses/Check.IsTrimmedAtStart.cs b/Code/Light.GuardClauses/Check.IsTrimmedAtStart.cs new file mode 100644 index 0000000..3e2e3d1 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsTrimmedAtStart.cs @@ -0,0 +1,37 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified string is trimmed at the start, i.e. it does not start with + /// white space characters. Inputting an empty string will return true. + /// + /// The string to be checked. + /// + /// The value indicating whether true or false should be returned from this method when the + /// is null. The default value is true. + /// + /// + /// True if the is trimmed at the start, else false. + /// An empty string will result in true. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTrimmedAtStart(this string? parameter, bool regardNullAsTrimmed = true) => + parameter is null ? regardNullAsTrimmed : parameter.AsSpan().IsTrimmedAtStart(); + + /// + /// Checks if the specified character span is trimmed at the start, i.e. it does not start with + /// white space characters. Inputting an empty span will return true. + /// + /// The character span to be checked. + /// + /// True if the is trimmed at the start, else false. + /// An empty span will result in true. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsTrimmedAtStart(this ReadOnlySpan parameter) => + parameter.Length == 0 || !parameter[0].IsWhiteSpace(); +} diff --git a/Code/Light.GuardClauses/Check.IsValidEnumValue.cs b/Code/Light.GuardClauses/Check.IsValidEnumValue.cs new file mode 100644 index 0000000..4869f25 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsValidEnumValue.cs @@ -0,0 +1,18 @@ +using System; +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified value is a valid enum value of its type. This is true when the specified value + /// is one of the constants defined in the enum, or a valid flags combination when the enum type is marked + /// with the . + /// + /// The type of the enum. + /// The enum value to be checked. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsValidEnumValue(this T parameter) where T : struct, Enum => + EnumInfo.IsValidEnumValue(parameter); +} diff --git a/Code/Light.GuardClauses/Check.IsWhiteSpace.cs b/Code/Light.GuardClauses/Check.IsWhiteSpace.cs new file mode 100644 index 0000000..4a18250 --- /dev/null +++ b/Code/Light.GuardClauses/Check.IsWhiteSpace.cs @@ -0,0 +1,12 @@ +using System.Runtime.CompilerServices; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Checks if the specified character is a white space character. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsWhiteSpace(this char character) => char.IsWhiteSpace(character); +} diff --git a/Code/Light.GuardClauses/Check.MustBe.cs b/Code/Light.GuardClauses/Check.MustBe.cs new file mode 100644 index 0000000..722e499 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBe.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that is equal to using the default equality comparer, or otherwise throws a . + /// + /// The first value to be compared. + /// The other value to be compared. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when and are not equal. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MustBe( + this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!EqualityComparer.Default.Equals(parameter, other)) + { + Throw.ValuesNotEqual(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that is equal to using the default equality comparer, or otherwise throws your custom exception. + /// + /// The first value to be compared. + /// The other value to be compared. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when and are not equal. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MustBe(this T parameter, T other, Func exceptionFactory) + { + if (!EqualityComparer.Default.Equals(parameter, other)) + { + Throw.CustomException(exceptionFactory, parameter, other); + } + + return parameter; + } + + /// + /// Ensures that is equal to using the specified equality comparer, or otherwise throws a . + /// + /// The first value to be compared. + /// The other value to be compared. + /// The equality comparer used for comparing the two values. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when and are not equal. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("equalityComparer:null => halt")] + public static T MustBe( + this T parameter, + T other, + IEqualityComparer equalityComparer, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!equalityComparer.MustNotBeNull(nameof(equalityComparer), message).Equals(parameter, other)) + { + Throw.ValuesNotEqual(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that is equal to using the specified equality comparer, or otherwise throws your custom exception. + /// + /// The first value to be compared. + /// The other value to be compared. + /// The equality comparer used for comparing the two values. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// Your custom exception thrown when and are not equal, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("equalityComparer:null => halt")] + public static T MustBe( + this T parameter, + T other, + IEqualityComparer equalityComparer, + Func, Exception> exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (equalityComparer is null || !equalityComparer.Equals(parameter, other)) + { + Throw.CustomException(exceptionFactory, parameter, other, equalityComparer!); + } + + return parameter; + } + + /// + /// Ensures that the two strings are equal using the specified , or otherwise throws a . + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is not equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustBe( + this string? parameter, + string? other, + StringComparison comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!string.Equals(parameter, other, comparisonType)) + { + Throw.ValuesNotEqual(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the two strings are equal using the specified , or otherwise throws your custom exception. + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is not equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustBe( + this string? parameter, + string? other, + StringComparison comparisonType, + Func exceptionFactory + ) + { + if (!string.Equals(parameter, other, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, other, comparisonType); + } + + return parameter; + } + + /// + /// Ensures that the two strings are equal using the specified , or otherwise throws a . + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is not equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustBe( + this string? parameter, + string? other, + StringComparisonType comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.Equals(other, comparisonType)) + { + Throw.ValuesNotEqual(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the two strings are equal using the specified , or otherwise throws your custom exception. + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is not equal to . + /// Thrown when is not a valid value from the enum. + public static string? MustBe( + this string? parameter, + string? other, + StringComparisonType comparisonType, + Func exceptionFactory + ) + { + if (!parameter.Equals(other, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, other, comparisonType); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeAbsoluteUri.cs b/Code/Light.GuardClauses/Check.MustBeAbsoluteUri.cs new file mode 100644 index 0000000..88415b0 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeAbsoluteUri.cs @@ -0,0 +1,55 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified URI is an absolute one, or otherwise throws a . + /// + /// The URI to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is not an absolute URI. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeAbsoluteUri( + [NotNull] [ValidatedNotNull] this Uri? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri == false) + { + Throw.MustBeAbsoluteUri(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified URI is an absolute one, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The delegate that creates the exception to be thrown. is passed to this delegate. + /// Your custom exception thrown when is not an absolute URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeAbsoluteUri( + [NotNull] [ValidatedNotNull] this Uri? parameter, + Func exceptionFactory + ) + { + if (parameter is null || parameter.IsAbsoluteUri == false) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeEmailAddress.cs b/Code/Light.GuardClauses/Check.MustBeEmailAddress.cs new file mode 100644 index 0000000..920e55e --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeEmailAddress.cs @@ -0,0 +1,110 @@ +using System; +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is a valid email address using the default email regular expression + /// defined in , or otherwise throws an . + /// + /// The email address that will be validated. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is no valid email address. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeEmailAddress( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress()) + { + Throw.InvalidEmailAddress(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is a valid email address using the default email regular expression + /// defined in , or otherwise throws your custom exception. + /// + /// The email address that will be validated. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is null or no valid email address. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeEmailAddress( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (!parameter.IsEmailAddress()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } + + /// + /// Ensures that the string is a valid email address using the provided regular expression, + /// or otherwise throws an . + /// + /// The email address that will be validated. + /// The regular expression that determines if the input string is a valid email. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is no valid email address. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; emailAddressPattern:null => halt")] + public static string MustBeEmailAddress( + [NotNull] [ValidatedNotNull] this string? parameter, + Regex emailAddressPattern, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress(emailAddressPattern)) + { + Throw.InvalidEmailAddress(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is a valid email address using the provided regular expression, + /// or otherwise throws your custom exception. + /// + /// The email address that will be validated. + /// The regular expression that determines if the input string is a valid email. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or no valid email address. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; emailAddressPattern:null => halt")] + public static string MustBeEmailAddress( + [NotNull] [ValidatedNotNull] this string? parameter, + Regex emailAddressPattern, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (emailAddressPattern is null || !parameter.IsEmailAddress(emailAddressPattern)) + { + Throw.CustomException(exceptionFactory, parameter, emailAddressPattern!); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeGreaterThan.cs b/Code/Light.GuardClauses/Check.MustBeGreaterThan.cs new file mode 100644 index 0000000..c8b6234 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeGreaterThan.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is greater than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be less than . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is less than or equal to . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustBeGreaterThan( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) <= 0) + { + Throw.MustBeGreaterThan(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is greater than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be less than . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is less than or equal to , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustBeGreaterThan( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) <= 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeGreaterThanOrEqualTo.cs b/Code/Light.GuardClauses/Check.MustBeGreaterThanOrEqualTo.cs new file mode 100644 index 0000000..90cd127 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeGreaterThanOrEqualTo.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is not less than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be less than or equal to . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is less than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustBeGreaterThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) < 0) + { + Throw.MustBeGreaterThanOrEqualTo(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is not less than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be less than or equal to . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is less than , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustBeGreaterThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) < 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeHttpOrHttpsUrl.cs b/Code/Light.GuardClauses/Check.MustBeHttpOrHttpsUrl.cs new file mode 100644 index 0000000..a431469 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeHttpOrHttpsUrl.cs @@ -0,0 +1,58 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified URI has the "http" or "https" scheme, or otherwise throws an . + /// + /// The URI to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when uses a different scheme than "http" or "https". + /// Thrown when is relative and thus has no scheme. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeHttpOrHttpsUrl( + [NotNull] [ValidatedNotNull] this Uri? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustBeAbsoluteUri(parameterName, message).Scheme.Equals("https") == false && + parameter.Scheme.Equals("http") == false) + { + Throw.UriMustHaveOneSchemeOf(parameter, ["https", "http"], parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified URI has the "http" or "https" scheme, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The delegate that creates the exception to be thrown. is passed to this delegate. + /// Your custom exception thrown when uses a different scheme than "http" or "https", or when is a relative URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeHttpOrHttpsUrl( + [NotNull] [ValidatedNotNull] this Uri? parameter, + Func exceptionFactory + ) + { + if (parameter.MustBeAbsoluteUri(exceptionFactory).Scheme.Equals("https") == false && + parameter.Scheme.Equals("http") == false) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeHttpUrl.cs b/Code/Light.GuardClauses/Check.MustBeHttpUrl.cs new file mode 100644 index 0000000..717be5f --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeHttpUrl.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified URI has the "http" scheme, or otherwise throws an . + /// + /// The URI to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when uses a different scheme than "http". + /// Thrown when is relative and thus has no scheme. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeHttpUrl( + [NotNull] [ValidatedNotNull] this Uri? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) => + parameter.MustHaveScheme("http", parameterName, message); + + /// + /// Ensures that the specified URI has the "http" scheme, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The delegate that creates the exception to be thrown. is passed to this delegate. + /// Your custom exception thrown when uses a different scheme than "http", or when is a relative URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeHttpUrl( + [NotNull] [ValidatedNotNull] this Uri? parameter, + Func exceptionFactory + ) => + parameter.MustHaveScheme("http", exceptionFactory); +} diff --git a/Code/Light.GuardClauses/Check.MustBeHttpsUrl.cs b/Code/Light.GuardClauses/Check.MustBeHttpsUrl.cs new file mode 100644 index 0000000..4e2169c --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeHttpsUrl.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified URI has the "https" scheme, or otherwise throws an . + /// + /// The URI to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when uses a different scheme than "https". + /// Thrown when is relative and thus has no scheme. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeHttpsUrl( + [NotNull] [ValidatedNotNull] this Uri? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) => + parameter.MustHaveScheme("https", parameterName, message); + + /// + /// Ensures that the specified URI has the "https" scheme, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The delegate that creates the exception to be thrown. is passed to this delegate. + /// Your custom exception thrown when uses a different scheme than "https", or when is a relative URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeHttpsUrl( + [NotNull] [ValidatedNotNull] this Uri? parameter, + Func exceptionFactory + ) => + parameter.MustHaveScheme("https", exceptionFactory); +} diff --git a/Code/Light.GuardClauses/Check.MustBeIn.cs b/Code/Light.GuardClauses/Check.MustBeIn.cs new file mode 100644 index 0000000..b727d36 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeIn.cs @@ -0,0 +1,61 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that is within the specified range, or otherwise throws an . + /// + /// The type of the parameter to be checked. + /// The parameter to be checked. + /// The range where must be in-between. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is not within . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustBeIn( + [NotNull] [ValidatedNotNull] this T parameter, + Range range, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (!range.IsValueWithinRange(parameter.MustNotBeNullReference(parameterName, message))) + { + Throw.MustBeInRange(parameter, range, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that is within the specified range, or otherwise throws your custom exception. + /// + /// The parameter to be checked. + /// The range where must be in-between. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is not within , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustBeIn( + [NotNull] [ValidatedNotNull] this T parameter, + Range range, + Func, Exception> exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || !range.IsValueWithinRange(parameter)) + { + Throw.CustomException(exceptionFactory, parameter!, range); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeLessThan.cs b/Code/Light.GuardClauses/Check.MustBeLessThan.cs new file mode 100644 index 0000000..21faebd --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeLessThan.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is less than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be greater than . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is not less than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustBeLessThan( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) >= 0) + { + Throw.MustBeLessThan(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is less than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be greater than . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is not less than , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustBeLessThan( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) >= 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeLessThanOrEqualTo.cs b/Code/Light.GuardClauses/Check.MustBeLessThanOrEqualTo.cs new file mode 100644 index 0000000..9e813df --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeLessThanOrEqualTo.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is not greater than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be greater than or equal to . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is greater than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustBeLessThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) > 0) + { + Throw.MustBeLessThanOrEqualTo(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is not greater than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be greater than or equal to . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is greater than , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustBeLessThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) > 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeLocal.cs b/Code/Light.GuardClauses/Check.MustBeLocal.cs new file mode 100644 index 0000000..5a41690 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeLocal.cs @@ -0,0 +1,49 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified uses , or otherwise throws an . + /// + /// The date time to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not use . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DateTime MustBeLocal( + this DateTime parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Kind != DateTimeKind.Local) + { + Throw.MustBeLocalDateTime(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified uses , or otherwise throws your custom exception. + /// + /// The date time to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when does not use . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static DateTime MustBeLocal(this DateTime parameter, Func exceptionFactory) + { + if (parameter.Kind != DateTimeKind.Local) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeLongerThan.cs b/Code/Light.GuardClauses/Check.MustBeLongerThan.cs new file mode 100644 index 0000000..c884530 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeLongerThan.cs @@ -0,0 +1,151 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is longer than the specified length, or otherwise throws a . + /// + /// The string to be checked. + /// The length that the string must be longer than. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has a length shorter than or equal to . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeLongerThan( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).Length <= length) + { + Throw.StringNotLongerThan(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is longer than the specified length, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The length that the string must be longer than. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or when it has a length shorter than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeLongerThan( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + Func exceptionFactory + ) + { + if (parameter is null || parameter.Length <= length) + { + Throw.CustomException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The value that the span must be longer than. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is shorter than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeLongerThan( + this Span parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length <= length) + { + Throw.SpanMustBeLongerThan(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length value that the span must be longer than. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is shorter than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeLongerThan( + this Span parameter, + int length, + SpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length <= length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The value that the span must be longer than. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is shorter than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeLongerThan( + this ReadOnlySpan parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length <= length) + { + Throw.SpanMustBeLongerThan(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length value that the span must be longer than. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is shorter than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeLongerThan( + this ReadOnlySpan parameter, + int length, + ReadOnlySpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length <= length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeLongerThanOrEqualTo.cs b/Code/Light.GuardClauses/Check.MustBeLongerThanOrEqualTo.cs new file mode 100644 index 0000000..f2e98ec --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeLongerThanOrEqualTo.cs @@ -0,0 +1,151 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is longer than or equal to the specified length, or otherwise throws a . + /// + /// The string to be checked. + /// The length that the string must be longer than or equal to. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has a length shorter than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeLongerThanOrEqualTo( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).Length < length) + { + Throw.StringNotLongerThanOrEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is longer than or equal to the specified length, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The length that the string must be longer than or equal to. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or when it has a length shorter than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeLongerThanOrEqualTo( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + Func exceptionFactory + ) + { + if (parameter is null || parameter.Length < length) + { + Throw.CustomException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than or equal to the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The value that the span must be longer than or equal to. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is shorter than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeLongerThanOrEqualTo( + this Span parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length < length) + { + Throw.SpanMustBeLongerThanOrEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than or equal to the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The value that the span must be longer than or equal to. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is shorter than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeLongerThanOrEqualTo( + this Span parameter, + int length, + SpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length < length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than or equal to the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The value that the span must be longer than or equal to. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is shorter than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeLongerThanOrEqualTo( + this ReadOnlySpan parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length < length) + { + Throw.SpanMustBeLongerThanOrEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is longer than or equal to the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The value that the span must be longer than or equal to. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is shorter than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeLongerThanOrEqualTo( + this ReadOnlySpan parameter, + int length, + ReadOnlySpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length < length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeNewLine.cs b/Code/Light.GuardClauses/Check.MustBeNewLine.cs new file mode 100644 index 0000000..c5fef10 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeNewLine.cs @@ -0,0 +1,55 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is either "\n" or "\r\n", or otherwise throws a . This is done independently of the current value of . + /// + /// The string to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is not equal to "\n" or "\r\n". + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeNewLine( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).IsNewLine()) + { + Throw.NotNewLine(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is either "\n" or "\r\n", or otherwise throws your custom exception. This is done independently of the current value of . + /// + /// The string to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is not equal to "\n" or "\r\n". + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeNewLine( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (!parameter.IsNewLine()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeOfType.cs b/Code/Light.GuardClauses/Check.MustBeOfType.cs new file mode 100644 index 0000000..bbf9001 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeOfType.cs @@ -0,0 +1,47 @@ + +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that can be cast to and returns the cast value, or otherwise throws a . + /// + /// The value to be cast. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when cannot be cast to . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) + { + if (parameter.MustNotBeNull(parameterName, message) is T castValue) + return castValue; + + Throw.InvalidTypeCast(parameter, typeof(T), parameterName, message); + return default; + } + + /// + /// Ensures that can be cast to and returns the cast value, or otherwise throws your custom exception. + /// + /// The value to be cast. + /// The delegate that creates your custom exception. The is passed to this delegate. + /// Your custom exception thrown when cannot be cast to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustBeOfType([NotNull, ValidatedNotNull, NoEnumeration] this object? parameter, Func exceptionFactory) + { + if (parameter is T castValue) + return castValue; + + Throw.CustomException(exceptionFactory, parameter); + return default; + } +} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.MustBeOneOf.cs b/Code/Light.GuardClauses/Check.MustBeOneOf.cs new file mode 100644 index 0000000..6d70417 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeOneOf.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the value is one of the specified items, or otherwise throws a . + /// + /// The value to be checked. + /// The items that should contain the value. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is not equal to one of the specified . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("items:null => halt")] + public static TItem MustBeOneOf( + this TItem parameter, + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + [NotNull] [ValidatedNotNull] IEnumerable items, + [CallerArgumentExpression("parameter")] + string? parameterName = null, + string? message = null + ) + { + // ReSharper disable PossibleMultipleEnumeration + if (!parameter.IsOneOf(items.MustNotBeNull(nameof(items), message))) + { + Throw.ValueNotOneOf(parameter, items, parameterName, message); + } + + return parameter; + // ReSharper restore PossibleMultipleEnumeration + } + + /// + /// Ensures that the value is one of the specified items, or otherwise throws your custom exception. + /// + /// The value to be checked. + /// The items that should contain the value. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is not equal to one of the specified , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("items:null => halt")] + public static TItem MustBeOneOf( + this TItem parameter, + [NotNull] [ValidatedNotNull] TCollection items, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (items is null || !parameter.IsOneOf(items)) + { + Throw.CustomException(exceptionFactory, parameter, items!); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeRelativeUri.cs b/Code/Light.GuardClauses/Check.MustBeRelativeUri.cs new file mode 100644 index 0000000..6864c3d --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeRelativeUri.cs @@ -0,0 +1,55 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified URI is a relative one, or otherwise throws an . + /// + /// The URI to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is an absolute URI. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeRelativeUri( + [NotNull] [ValidatedNotNull] this Uri? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri) + { + Throw.MustBeRelativeUri(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified URI is a relative one, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is an absolute URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustBeRelativeUri( + [NotNull] [ValidatedNotNull] this Uri? parameter, + Func exceptionFactory + ) + { + if (parameter is null || parameter.IsAbsoluteUri) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeShorterThan.cs b/Code/Light.GuardClauses/Check.MustBeShorterThan.cs new file mode 100644 index 0000000..f871358 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeShorterThan.cs @@ -0,0 +1,151 @@ +using System; +using System.Runtime.CompilerServices; +using Light.GuardClauses.Exceptions; +using JetBrains.Annotations; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is shorter than the specified length, or otherwise throws a . + /// + /// The string to be checked. + /// The length that the string must be shorter than. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has a length greater than or equal to . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeShorterThan( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).Length >= length) + { + Throw.StringNotShorterThan(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is shorter than the specified length, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The length that the string must be shorter than. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or when it has a length greater than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeShorterThan( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + Func exceptionFactory + ) + { + if (parameter is null || parameter.Length >= length) + { + Throw.CustomException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The length value that the span must be shorter than. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is longer than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeShorterThan( + this Span parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length >= length) + { + Throw.SpanMustBeShorterThan(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length value that the span must be shorter than. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is longer than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeShorterThan( + this Span parameter, + int length, + SpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length >= length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The length value that the span must be shorter than. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is longer than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeShorterThan( + this ReadOnlySpan parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length >= length) + { + Throw.SpanMustBeShorterThan(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length value that the span must be shorter than. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is longer than or equal to . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeShorterThan( + this ReadOnlySpan parameter, + int length, + ReadOnlySpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length >= length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeShorterThanOrEqualTo.cs b/Code/Light.GuardClauses/Check.MustBeShorterThanOrEqualTo.cs new file mode 100644 index 0000000..20f2de8 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeShorterThanOrEqualTo.cs @@ -0,0 +1,151 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is shorter than or equal to the specified length, or otherwise throws a . + /// + /// The string to be checked. + /// The length that the string must be shorter than or equal to. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has a length greater than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeShorterThanOrEqualTo( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).Length > length) + { + Throw.StringNotShorterThanOrEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is shorter than or equal to the specified length, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The length that the string must be shorter than or equal to. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or when it has a length greater than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeShorterThanOrEqualTo( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + Func exceptionFactory + ) + { + if (parameter is null || parameter.Length > length) + { + Throw.CustomException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The length value that the span must be shorter than or equal to. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is longer than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeShorterThanOrEqualTo( + this Span parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length > length) + { + Throw.SpanMustBeShorterThanOrEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length value that the span must be shorter than or equal to. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is longer than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Span MustBeShorterThanOrEqualTo( + this Span parameter, + int length, + SpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length > length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The length value that the span must be shorter than or equal to. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is longer than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeShorterThanOrEqualTo( + this ReadOnlySpan parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length > length) + { + Throw.SpanMustBeShorterThanOrEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span is shorter than or equal to the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length value that the span must be shorter than or equal to. + /// The delegate that creates your custom exception. and are passed to it. + /// Your custom exception thrown when is longer than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustBeShorterThanOrEqualTo( + this ReadOnlySpan parameter, + int length, + ReadOnlySpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length > length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeSubstringOf.cs b/Code/Light.GuardClauses/Check.MustBeSubstringOf.cs new file mode 100644 index 0000000..63fd7f9 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeSubstringOf.cs @@ -0,0 +1,127 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is a substring of the specified other string, or otherwise throws a . + /// + /// The string to be checked. + /// The other string that must contain . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain . + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) + { + Throw.NotSubstring(parameter, value, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is a substring of the specified other string, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must contain . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not contain , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || !value.Contains(parameter)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + + return parameter; + } + + /// + /// Ensures that the string is a substring of the specified other string, or otherwise throws a . + /// + /// The string to be checked. + /// The other string that must contain . + /// One of the enumeration values that specifies the rules for the search. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain . + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + + value.MustNotBeNull(nameof(value), message); + parameter.MustNotBeNull(parameterName, message); + if (value.IndexOf(parameter, comparisonType) == -1) + { + Throw.NotSubstring(parameter, value, comparisonType, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is a substring of the specified other string, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must contain . + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when does not contain , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || value.IndexOf(parameter, comparisonType) == -1) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeTrimmed.cs b/Code/Light.GuardClauses/Check.MustBeTrimmed.cs new file mode 100644 index 0000000..c4e163e --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeTrimmed.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is not null and trimmed, or otherwise throws a . + /// Empty strings are regarded as trimmed. + /// + /// The string to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// + /// Thrown when is not trimmed, i.e. they start or end with white space characters. + /// Empty strings are regarded as trimmed. + /// + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeTrimmed( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).IsTrimmed()) + { + Throw.NotTrimmed(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is not null and trimmed, or otherwise throws your custom exception. + /// Empty strings are regarded as trimmed. + /// + /// The string to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is null or not trimmed. Empty strings are regarded as trimmed. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeTrimmed( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (parameter is null || !parameter.AsSpan().IsTrimmed()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeTrimmedAtEnd.cs b/Code/Light.GuardClauses/Check.MustBeTrimmedAtEnd.cs new file mode 100644 index 0000000..de90549 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeTrimmedAtEnd.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is not null and trimmed at the end, or otherwise throws a . + /// Empty strings are regarded as trimmed. + /// + /// The string to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// + /// Thrown when is not trimmed at the end, i.e. they end with white space characters. + /// Empty strings are regarded as trimmed. + /// + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeTrimmedAtEnd( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtEnd()) + { + Throw.NotTrimmedAtEnd(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is not null and trimmed at the end, or otherwise throws your custom exception. + /// Empty strings are regarded as trimmed. + /// + /// The string to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is null or not trimmed at the end. Empty strings are regarded as trimmed. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeTrimmedAtEnd( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (parameter is null || !parameter.AsSpan().IsTrimmedAtEnd()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeTrimmedAtStart.cs b/Code/Light.GuardClauses/Check.MustBeTrimmedAtStart.cs new file mode 100644 index 0000000..34dad8b --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeTrimmedAtStart.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is not null and trimmed at the start, or otherwise throws a . + /// Empty strings are regarded as trimmed. + /// + /// The string to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// + /// Thrown when is not trimmed at the start, i.e. they start with white space characters. + /// Empty strings are regarded as trimmed. + /// + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeTrimmedAtStart( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtStart()) + { + Throw.NotTrimmedAtStart(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is not null and trimmed at the start, or otherwise throws your custom exception. + /// Empty strings are regarded as trimmed. + /// + /// The string to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is null or not trimmed at the start. Empty strings are regarded as trimmed. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustBeTrimmedAtStart( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (parameter is null || !parameter.AsSpan().IsTrimmedAtStart()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeUnspecified.cs b/Code/Light.GuardClauses/Check.MustBeUnspecified.cs new file mode 100644 index 0000000..97810eb --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeUnspecified.cs @@ -0,0 +1,49 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified uses , or otherwise throws an . + /// + /// The date time to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not use . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DateTime MustBeUnspecified( + this DateTime parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Kind != DateTimeKind.Unspecified) + { + Throw.MustBeUnspecifiedDateTime(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified uses , or otherwise throws your custom exception. + /// + /// The date time to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when does not use . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static DateTime MustBeUnspecified(this DateTime parameter, Func exceptionFactory) + { + if (parameter.Kind != DateTimeKind.Unspecified) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeUtc.cs b/Code/Light.GuardClauses/Check.MustBeUtc.cs new file mode 100644 index 0000000..efa2369 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeUtc.cs @@ -0,0 +1,49 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified uses , or otherwise throws an . + /// + /// The date time to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not use . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static DateTime MustBeUtc( + this DateTime parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Kind != DateTimeKind.Utc) + { + Throw.MustBeUtcDateTime(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified uses , or otherwise throws your custom exception. + /// + /// The date time to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when does not use . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static DateTime MustBeUtc(this DateTime parameter, Func exceptionFactory) + { + if (parameter.Kind != DateTimeKind.Utc) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustBeValidEnumValue.cs b/Code/Light.GuardClauses/Check.MustBeValidEnumValue.cs new file mode 100644 index 0000000..9672a6d --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustBeValidEnumValue.cs @@ -0,0 +1,57 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified enum value is valid, or otherwise throws an . An enum value + /// is valid when the specified value is one of the constants defined in the enum, or a valid flags combination when the enum type + /// is marked with the . + /// + /// The type of the enum. + /// The value to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is no valid enum value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MustBeValidEnumValue( + this T parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + where T : struct, Enum + { + if (!EnumInfo.IsValidEnumValue(parameter)) + { + Throw.EnumValueNotDefined(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified enum value is valid, or otherwise throws your custom exception. An enum value + /// is valid when the specified value is one of the constants defined in the enum, or a valid flags combination when the enum type + /// is marked with the . + /// + /// The type of the enum. + /// The value to be checked. + /// The delegate that creates your custom exception. The is passed to this delegate. + /// Your custom exception thrown when is no valid enum value, or when is no enum type. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static T MustBeValidEnumValue(this T parameter, Func exceptionFactory) + where T : struct, Enum + { + if (!EnumInfo.IsValidEnumValue(parameter)) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustContain.cs b/Code/Light.GuardClauses/Check.MustContain.cs new file mode 100644 index 0000000..24b7175 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustContain.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the collection contains the specified item, or otherwise throws a . + /// + /// The collection to be checked. + /// The item that must be part of the collection. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustContain( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + TItem item, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where TCollection : class, IEnumerable + { + if (parameter is ICollection collection) + { + if (!collection.Contains(item)) + { + Throw.MissingItem(parameter, item, parameterName, message); + } + + return parameter; + } + + if (!parameter.MustNotBeNull(parameterName, message).Contains(item)) + { + Throw.MissingItem(parameter, item, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the collection contains the specified item, or otherwise throws your custom exception. + /// + /// The collection to be checked. + /// The item that must be part of the collection. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when does not contain , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustContain( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + TItem item, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is ICollection collection) + { + if (!collection.Contains(item)) + { + Throw.CustomException(exceptionFactory, parameter, item); + } + + return parameter; + } + + if (parameter is null || !parameter.Contains(item)) + { + Throw.CustomException(exceptionFactory, parameter, item); + } + + return parameter; + } + + /// + /// Ensures that the string contains the specified substring, or otherwise throws a . + /// + /// The string to be checked. + /// The substring that must be part of . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain . + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string? value, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) + { + Throw.StringDoesNotContain(parameter, value, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string contains the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The substring that must be part of . + /// The delegate that creates you custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not contain , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || !parameter.Contains(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + + return parameter; + } + + /// + /// Ensures that the string contains the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The substring that must be part of . + /// One of the enumeration values that specifies the rules for the search. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain . + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).IndexOf( + value.MustNotBeNull(nameof(value), message), + comparisonType + ) < + 0) + { + Throw.StringDoesNotContain(parameter, value, comparisonType, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string contains the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The substring that must be part of . + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates you custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when does not contain , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || parameter.IndexOf(value, comparisonType) < 0) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustEndWith.cs b/Code/Light.GuardClauses/Check.MustEndWith.cs new file mode 100644 index 0000000..06dc8b2 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustEndWith.cs @@ -0,0 +1,94 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- Caller might have NRTs switched off + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string ends with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must end with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not end with . + /// Thrown when or is null. + /// Thrown when is not a valid value. + public static string MustEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).EndsWith(value, comparisonType)) + { + Throw.StringDoesNotEndWith(parameter, value, comparisonType, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the string ends with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must end with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not end with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !parameter.EndsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string ends with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must end with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when does not end with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !parameter.EndsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveCount.cs b/Code/Light.GuardClauses/Check.MustHaveCount.cs new file mode 100644 index 0000000..3c88fad --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveCount.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using Light.GuardClauses.FrameworkExtensions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the collection has the specified number of items, or otherwise throws an . + /// + /// The collection to be checked. + /// The number of items the collection 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 number of items. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustHaveCount( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + int count, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where TCollection : class, IEnumerable + { + if (parameter!.Count(parameterName, message) != count) + { + Throw.InvalidCollectionCount(parameter, count, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the collection has the specified number of items, or otherwise throws your custom exception. + /// + /// The collection to be checked. + /// The number of items the collection 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 number of items, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustHaveCount( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + int count, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is null || parameter.Count() != count) + { + Throw.CustomException(exceptionFactory, parameter, count); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveLength.cs b/Code/Light.GuardClauses/Check.MustHaveLength.cs new file mode 100644 index 0000000..d912c6b --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveLength.cs @@ -0,0 +1,151 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string has the specified length, or otherwise throws a . + /// + /// The string to be checked. + /// The asserted length of the string. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has a length other than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustHaveLength( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).Length != length) + { + Throw.StringLengthNotEqualTo(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string has the specified length, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The asserted length of the string. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or when it has a length other than . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustHaveLength( + [NotNull] [ValidatedNotNull] this string? parameter, + int length, + Func exceptionFactory + ) + { + if (parameter is null || parameter.Length != length) + { + Throw.CustomException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span has the specified length, or otherwise throws an . + /// + /// The span to be checked. + /// The length that the span 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 Span MustHaveLength( + this Span parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length != length) + { + Throw.InvalidSpanLength(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span has the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length that the span 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 Span MustHaveLength( + this Span parameter, + int length, + SpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length != length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } + + /// + /// Ensures that the span has the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length that the span must have. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Your custom exception thrown when does not have the specified length. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ReadOnlySpan MustHaveLength( + this ReadOnlySpan parameter, + int length, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Length != length) + { + Throw.InvalidSpanLength(parameter, length, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the span has the specified length, or otherwise throws your custom exception. + /// + /// The span to be checked. + /// The length that the span 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 ReadOnlySpan MustHaveLength( + this ReadOnlySpan parameter, + int length, + ReadOnlySpanExceptionFactory exceptionFactory + ) + { + if (parameter.Length != length) + { + Throw.CustomSpanException(exceptionFactory, parameter, length); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveLengthIn.cs b/Code/Light.GuardClauses/Check.MustHaveLengthIn.cs new file mode 100644 index 0000000..340d142 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveLengthIn.cs @@ -0,0 +1,59 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string's length is within the specified range, or otherwise throws a . + /// + /// The string to be checked. + /// The range where the string'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 with the specified . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustHaveLengthIn( + [NotNull] [ValidatedNotNull] this string? parameter, + Range range, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!range.IsValueWithinRange(parameter.MustNotBeNull(parameterName, message).Length)) + { + Throw.StringLengthNotInRange(parameter, range, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string's length is within the specified range, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The range where the string's length must be in-between. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is null or its length is not within the specified range. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustHaveLengthIn( + [NotNull] [ValidatedNotNull] this string? parameter, + Range range, + Func, Exception> exceptionFactory + ) + { + if (parameter is null || !range.IsValueWithinRange(parameter.Length)) + { + Throw.CustomException(exceptionFactory, parameter, range); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveMaximumCount.cs b/Code/Light.GuardClauses/Check.MustHaveMaximumCount.cs new file mode 100644 index 0000000..b141e55 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveMaximumCount.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using Light.GuardClauses.FrameworkExtensions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the collection has at most the specified number of items, or otherwise throws an . + /// + /// The collection to be checked. + /// The number of items the collection should have at most. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain at most the specified number of items. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustHaveMaximumCount( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + int count, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where TCollection : class, IEnumerable + { + if (parameter.Count(parameterName, message) > count) + { + Throw.InvalidMaximumCollectionCount(parameter, count, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the collection has at most the specified number of items, or otherwise throws your custom exception. + /// + /// The collection to be checked. + /// The number of items the collection should have at most. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when does not contain at most the specified number of items, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustHaveMaximumCount( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + int count, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is null || parameter.Count() > count) + { + Throw.CustomException(exceptionFactory, parameter, count); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveMinimumCount.cs b/Code/Light.GuardClauses/Check.MustHaveMinimumCount.cs new file mode 100644 index 0000000..c858def --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveMinimumCount.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using Light.GuardClauses.FrameworkExtensions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the collection has at least the specified number of items, or otherwise throws an . + /// + /// The collection to be checked. + /// The number of items the collection should have at least. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not contain at least the specified number of items. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustHaveMinimumCount( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + int count, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where TCollection : class, IEnumerable + { + if (parameter.Count(parameterName, message) < count) + { + Throw.InvalidMinimumCollectionCount(parameter, count, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the collection has at least the specified number of items, or otherwise throws your custom exception. + /// + /// The collection to be checked. + /// The number of items the collection should have at least. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when does not contain at least the specified number of items, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustHaveMinimumCount( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + int count, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is null || parameter.Count() < count) + { + Throw.CustomException(exceptionFactory, parameter, count); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveOneSchemeOf.cs b/Code/Light.GuardClauses/Check.MustHaveOneSchemeOf.cs new file mode 100644 index 0000000..19e6b80 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveOneSchemeOf.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the URI has one of the specified schemes, or otherwise throws an . + /// + /// The URI to be checked. + /// One of these strings must be equal to the scheme of the URI. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the scheme is not equal to one of the specified schemes. + /// Thrown when is relative and thus has no scheme. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; schemes:null => halt")] + public static Uri MustHaveOneSchemeOf( + [NotNull] [ValidatedNotNull] this Uri? parameter, + IEnumerable schemes, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + // ReSharper disable PossibleMultipleEnumeration + parameter.MustBeAbsoluteUri(parameterName, message); + + if (schemes is ICollection collection) + { + if (!collection.Contains(parameter.Scheme)) + { + Throw.UriMustHaveOneSchemeOf(parameter, schemes, parameterName, message); + } + + return parameter; + } + + if (!schemes.MustNotBeNull(nameof(schemes), message).Contains(parameter.Scheme)) + { + Throw.UriMustHaveOneSchemeOf(parameter, schemes, parameterName, message); + } + + return parameter; + // ReSharper restore PossibleMultipleEnumeration + } + + /// + /// Ensures that the URI has one of the specified schemes, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// One of these strings must be equal to the scheme of the URI. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the scheme is not equal to one of the specified schemes, or when is a relative URI, or when is null. + /// Thrown when is null. + /// The type of the collection containing the schemes. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustHaveOneSchemeOf( + [NotNull] [ValidatedNotNull] this Uri? parameter, + TCollection schemes, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is null || !parameter.IsAbsoluteUri) + { + Throw.CustomException(exceptionFactory, parameter, schemes); + } + + if (schemes is ICollection collection) + { + if (!collection.Contains(parameter.Scheme)) + { + Throw.CustomException(exceptionFactory, parameter, schemes); + } + + return parameter; + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (schemes is null || !schemes.Contains(parameter.Scheme)) + { + Throw.CustomException(exceptionFactory, parameter, schemes!); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveScheme.cs b/Code/Light.GuardClauses/Check.MustHaveScheme.cs new file mode 100644 index 0000000..aef3ae0 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveScheme.cs @@ -0,0 +1,83 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the has the specified scheme, or otherwise throws an . + /// + /// The URI to be checked. + /// The scheme that the URI should have. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when uses a different scheme than the specified one. + /// Thrown when is relative and thus has no scheme. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustHaveScheme( + [NotNull] [ValidatedNotNull] this Uri? parameter, + string scheme, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (string.Equals(parameter.MustBeAbsoluteUri(parameterName, message).Scheme, scheme) == false) + { + Throw.UriMustHaveScheme(parameter, scheme, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the has the specified scheme, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The scheme that the URI should have. + /// The delegate that creates the exception to be thrown. is passed to this delegate. + /// Your custom exception thrown when uses a different scheme than the specified one, or when is a relative URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustHaveScheme( + [NotNull] [ValidatedNotNull] this Uri? parameter, + string scheme, + Func exceptionFactory + ) + { + if (string.Equals(parameter.MustBeAbsoluteUri(exceptionFactory).Scheme, scheme) == false) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } + + /// + /// Ensures that the has the specified scheme, or otherwise throws your custom exception. + /// + /// The URI to be checked. + /// The scheme that the URI should have. + /// The delegate that creates the exception to be thrown. and are passed to this delegate. + /// Your custom exception thrown when uses a different scheme than the specified one, or when is a relative URI, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static Uri MustHaveScheme( + [NotNull] [ValidatedNotNull] this Uri? parameter, + string scheme, + Func exceptionFactory + ) + { + if (parameter is null || !parameter.IsAbsoluteUri || parameter.Scheme.Equals(scheme) == false) + { + Throw.CustomException(exceptionFactory, parameter, scheme); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustHaveValue.cs b/Code/Light.GuardClauses/Check.MustHaveValue.cs new file mode 100644 index 0000000..b20b452 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustHaveValue.cs @@ -0,0 +1,51 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified nullable has a value and returns it, or otherwise throws a . + /// + /// The nullable to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has no value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MustHaveValue( + [NotNull, NoEnumeration] this T? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : struct + { + if (!parameter.HasValue) + { + Throw.NullableHasNoValue(parameterName, message); + } + + return parameter.Value; + } + + /// + /// Ensures that the specified nullable has a value and returns it, or otherwise throws your custom exception. + /// + /// The nullable to be checked. + /// The delegate that creates your custom exception. + /// Thrown when has no value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static T MustHaveValue([NotNull, NoEnumeration] this T? parameter, Func exceptionFactory) + where T : struct + { + if (!parameter.HasValue) + { + Throw.CustomException(exceptionFactory); + } + + return parameter.Value; + } +} diff --git a/Code/Light.GuardClauses/Check.MustMatch.cs b/Code/Light.GuardClauses/Check.MustMatch.cs new file mode 100644 index 0000000..591e357 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustMatch.cs @@ -0,0 +1,64 @@ +using System; +using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string matches the specified regular expression, or otherwise throws a . + /// + /// The string to be checked. + /// The regular expression used for pattern matching. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not match the specified regular expression. + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; regex:null => halt")] + public static string MustMatch( + [NotNull] [ValidatedNotNull] this string? parameter, + Regex regex, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!regex.MustNotBeNull(nameof(regex), message).IsMatch(parameter.MustNotBeNull(parameterName, message))) + { + Throw.StringDoesNotMatch(parameter, regex, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string matches the specified regular expression, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The regular expression used for pattern matching. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not match the specified regular expression, + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string MustMatch( + [NotNull] [ValidatedNotNull] this string? parameter, + Regex regex, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || regex is null || !regex.IsMatch(parameter)) + { + Throw.CustomException(exceptionFactory, parameter, regex!); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBe.cs b/Code/Light.GuardClauses/Check.MustNotBe.cs new file mode 100644 index 0000000..93b4ced --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBe.cs @@ -0,0 +1,206 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that is not equal to using the default equality comparer, or otherwise throws a . + /// + /// The first value to be compared. + /// The other value to be compared. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when and are equal. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MustNotBe( + this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (EqualityComparer.Default.Equals(parameter, other)) + { + Throw.ValuesEqual(parameter, other, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that is not equal to using the default equality comparer, or otherwise throws your custom exception. + /// + /// The first value to be compared. + /// The other value to be compared. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when and are equal. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T MustNotBe(this T parameter, T other, Func exceptionFactory) + { + if (EqualityComparer.Default.Equals(parameter, other)) + { + Throw.CustomException(exceptionFactory, parameter, other); + } + return parameter; + } + + /// + /// Ensures that is not equal to using the specified equality comparer, or otherwise throws a . + /// + /// The first value to be compared. + /// The other value to be compared. + /// The equality comparer used for comparing the two values. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when and are equal. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("equalityComparer:null => halt")] + public static T MustNotBe( + this T parameter, + T other, + IEqualityComparer equalityComparer, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (equalityComparer.MustNotBeNull(nameof(equalityComparer), message).Equals(parameter, other)) + { + Throw.ValuesEqual(parameter, other, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that is not equal to using the specified equality comparer, or otherwise throws your custom exception. + /// + /// The first value to be compared. + /// The other value to be compared. + /// The equality comparer used for comparing the two values. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// Your custom exception thrown when and are equal, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("equalityComparer:null => halt")] + public static T MustNotBe( + this T parameter, + T other, + IEqualityComparer equalityComparer, + Func, Exception> exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (equalityComparer is null || equalityComparer.Equals(parameter, other)) + { + Throw.CustomException(exceptionFactory, parameter, other, equalityComparer!); + } + return parameter; + } + + /// + /// Ensures that the two strings are not equal using the specified , or otherwise throws a . + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustNotBe( + this string? parameter, + string? other, + StringComparison comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (string.Equals(parameter, other, comparisonType)) + { + Throw.ValuesEqual(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the two strings are not equal using the specified , or otherwise throws your custom exception. + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// Your custom exception thrown when is equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustNotBe( + this string? parameter, + string? other, + StringComparison comparisonType, + Func exceptionFactory + ) + { + if (string.Equals(parameter, other, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, other); + } + + return parameter; + } + + /// + /// Ensures that the two strings are not equal using the specified , or otherwise throws a . + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustNotBe( + this string? parameter, + string? other, + StringComparisonType comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.Equals(other, comparisonType)) + { + Throw.ValuesEqual(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the two strings are not equal using the specified , or otherwise throws your custom exception. + /// + /// The first string to be compared. + /// The second string to be compared. + /// The enum value specifying how the two strings should be compared. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// Your custom exception thrown when is equal to . + /// Thrown when is not a valid value from the enum. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static string? MustNotBe( + this string? parameter, + string? other, + StringComparisonType comparisonType, + Func exceptionFactory + ) + { + if (parameter.Equals(other, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, other, comparisonType); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeDefault.cs b/Code/Light.GuardClauses/Check.MustNotBeDefault.cs new file mode 100644 index 0000000..d2fade3 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeDefault.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified parameter is not the default value, or otherwise throws an + /// for reference types, or an for value types. + /// + /// The value to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is a reference type and null. + /// Thrown when is a value type and the default value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeDefault( + [NotNull, ValidatedNotNull] this T parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (default(T) is null) + { + if (parameter is null) + { + Throw.ArgumentNull(parameterName, message); + } + + return parameter; + } + + if (EqualityComparer.Default.Equals(parameter, default!)) + { + Throw.ArgumentDefault(parameterName, message); + } + +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. + return parameter; +#pragma warning restore CS8777 + } + + /// + /// Ensures that the specified parameter is not the default value, or otherwise throws your custom exception. + /// + /// The value to be checked. + /// The delegate that creates your custom exception. + /// Your custom exception thrown when is the default value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeDefault( + [NotNull, ValidatedNotNull] this T parameter, + Func exceptionFactory + ) + { + if (default(T) is null) + { + if (parameter is null) + { + Throw.CustomException(exceptionFactory); + } + + return parameter; + } + + if (EqualityComparer.Default.Equals(parameter, default!)) + { + Throw.CustomException(exceptionFactory); + } + +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. + return parameter; +#pragma warning restore CS8777 + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeEmpty.cs b/Code/Light.GuardClauses/Check.MustNotBeEmpty.cs new file mode 100644 index 0000000..f933994 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeEmpty.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified GUID is not empty, or otherwise throws an . + /// + /// The GUID to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is an empty GUID. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Guid MustNotBeEmpty( + this Guid parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter == Guid.Empty) + { + Throw.EmptyGuid(parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the specified GUID is not empty, or otherwise throws your custom exception. + /// + /// The GUID to be checked. + /// The delegate that creates your custom exception. + /// Your custom exception thrown when is an empty GUID. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("exceptionFactory:null => halt")] + public static Guid MustNotBeEmpty(this Guid parameter, Func exceptionFactory) + { + if (parameter == Guid.Empty) + { + Throw.CustomException(exceptionFactory); + } + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeGreaterThan.cs b/Code/Light.GuardClauses/Check.MustNotBeGreaterThan.cs new file mode 100644 index 0000000..4c02346 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeGreaterThan.cs @@ -0,0 +1,45 @@ +using System; +using JetBrains.Annotations; +using System.Runtime.CompilerServices; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is not greater than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be greater than or equal to . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is greater than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) > 0) + Throw.MustNotBeGreaterThan(parameter, other, parameterName, message); + return parameter; + } + + /// + /// Ensures that the specified is not greater than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be greater than or equal to . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is greater than , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeGreaterThan([NotNull, ValidatedNotNull] this T parameter, T other, Func exceptionFactory) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) > 0) + Throw.CustomException(exceptionFactory, parameter!, other); + return parameter; + } +} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.MustNotBeGreaterThanOrEqualTo.cs b/Code/Light.GuardClauses/Check.MustNotBeGreaterThanOrEqualTo.cs new file mode 100644 index 0000000..26a996e --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeGreaterThanOrEqualTo.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is less than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be greater than . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is not less than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeGreaterThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) >= 0) + { + Throw.MustNotBeGreaterThanOrEqualTo(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is less than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be greater than . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is not less than , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeGreaterThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) >= 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeIn.cs b/Code/Light.GuardClauses/Check.MustNotBeIn.cs new file mode 100644 index 0000000..4b7a385 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeIn.cs @@ -0,0 +1,61 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that is not within the specified range, or otherwise throws an . + /// + /// The type of the parameter to be checked. + /// The parameter to be checked. + /// The range where must not be in-between. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is within . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeIn( + [NotNull] [ValidatedNotNull] this T parameter, + Range range, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (range.IsValueWithinRange(parameter.MustNotBeNullReference(parameterName, message))) + { + Throw.MustNotBeInRange(parameter, range, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that is not within the specified range, or otherwise throws your custom exception. + /// + /// The parameter to be checked. + /// The range where must not be in-between. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is within , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeIn( + [NotNull] [ValidatedNotNull] this T parameter, + Range range, + Func, Exception> exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || range.IsValueWithinRange(parameter)) + { + Throw.CustomException(exceptionFactory, parameter!, range); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeLessThan.cs b/Code/Light.GuardClauses/Check.MustNotBeLessThan.cs new file mode 100644 index 0000000..e3f21b7 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeLessThan.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is not less than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be less than or equal to . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is less than . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeLessThan( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) < 0) + { + Throw.MustNotBeLessThan(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is not less than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be less than or equal to . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is less than , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeLessThan( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) < 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeLessThanOrEqualTo.cs b/Code/Light.GuardClauses/Check.MustNotBeLessThanOrEqualTo.cs new file mode 100644 index 0000000..86b0574 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeLessThanOrEqualTo.cs @@ -0,0 +1,60 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified is greater than the given value, or otherwise throws an . + /// + /// The comparable to be checked. + /// The boundary value that must be less than . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when the specified is less than or equal to . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeLessThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : IComparable + { + if (parameter.MustNotBeNullReference(parameterName, message).CompareTo(other) <= 0) + { + Throw.MustNotBeLessThanOrEqualTo(parameter, other, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified is greater than the given value, or otherwise throws your custom exception. + /// + /// The comparable to be checked. + /// The boundary value that must be less than . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when the specified is less than or equal to , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeLessThanOrEqualTo( + [NotNull] [ValidatedNotNull] this T parameter, + T other, + Func exceptionFactory + ) where T : IComparable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || parameter.CompareTo(other) <= 0) + { + Throw.CustomException(exceptionFactory, parameter!, other); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeNull.cs b/Code/Light.GuardClauses/Check.MustNotBeNull.cs new file mode 100644 index 0000000..544a57b --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeNull.cs @@ -0,0 +1,56 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified object reference is not null, or otherwise throws an . + /// + /// The object reference to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeNull( + [NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + where T : class + { + if (parameter is null) + { + Throw.ArgumentNull(parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified object reference is not null, or otherwise throws your custom exception. + /// + /// The reference to be checked. + /// The delegate that creates your custom exception. + /// Your custom exception thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeNull( + [NotNull, ValidatedNotNull, NoEnumeration] this T? parameter, + Func exceptionFactory + ) + where T : class + { + if (parameter is null) + { + Throw.CustomException(exceptionFactory); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeNullOrEmpty.cs b/Code/Light.GuardClauses/Check.MustNotBeNullOrEmpty.cs new file mode 100644 index 0000000..3ff1488 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeNullOrEmpty.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using Light.GuardClauses.FrameworkExtensions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the collection is not null or empty, or otherwise throws an . + /// + /// The collection to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when has no items. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustNotBeNullOrEmpty( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where TCollection : class, IEnumerable + { + if (parameter.Count(parameterName, message) == 0) + { + Throw.EmptyCollection(parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the collection is not null or empty, or otherwise throws your custom exception. + /// + /// The collection to be checked. + /// The delegate that creates your custom exception. + /// Thrown when has no items, or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustNotBeNullOrEmpty( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is null || parameter.Count() == 0) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } + + /// + /// Ensures that the specified string is not null or empty, or otherwise throws an or . + /// + /// The string to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is an empty string. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustNotBeNullOrEmpty( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter is null) + { + Throw.ArgumentNull(parameterName, message); + } + + if (parameter.Length == 0) + { + Throw.EmptyString(parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified string is not null or empty, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is an empty string or null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static string MustNotBeNullOrEmpty( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (parameter.IsNullOrEmpty()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeNullOrWhiteSpace.cs b/Code/Light.GuardClauses/Check.MustNotBeNullOrWhiteSpace.cs new file mode 100644 index 0000000..e93d21b --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeNullOrWhiteSpace.cs @@ -0,0 +1,62 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the specified string is not null, empty, or contains only white space, or otherwise throws an , an , or a . + /// + /// The string to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when contains only white space. + /// Thrown when is an empty string. + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustNotBeNullOrWhiteSpace( + [NotNull] [ValidatedNotNull] this string? parameter, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + parameter.MustNotBeNullOrEmpty(parameterName, message); + + foreach (var character in parameter) + { + if (!character.IsWhiteSpace()) + { + return parameter; + } + } + + Throw.WhiteSpaceString(parameter, parameterName, message); + return null; + } + + /// + /// Ensures that the specified string is not null, empty, or contains only white space, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Your custom exception thrown when is null, empty, or contains only white space. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory: null => halt")] + public static string MustNotBeNullOrWhiteSpace( + [NotNull] [ValidatedNotNull] this string? parameter, + Func exceptionFactory + ) + { + if (parameter.IsNullOrWhiteSpace()) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeNullReference.cs b/Code/Light.GuardClauses/Check.MustNotBeNullReference.cs new file mode 100644 index 0000000..ffd3ce3 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeNullReference.cs @@ -0,0 +1,77 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// 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, + /// use by default. + /// + /// The value to be checked for null. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is a reference type and is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static T MustNotBeNullReference( + [NotNull, ValidatedNotNull, NoEnumeration] + this T parameter, + [CallerArgumentExpression("parameter")] + string? parameterName = null, + string? message = null + ) + { + if (default(T) != null) + { + // If we end up here, parameter cannot be null +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. + return parameter; +#pragma warning restore CS8777 + } + + if (parameter is null) + { + Throw.ArgumentNull(parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the specified parameter is not null when is a reference type, or otherwise + /// throws your custom exception. PLEASE NOTICE: you should only use this assertion in generic contexts, + /// use by default. + /// + /// The value to be checked for null. + /// The delegate that creates your custom exception. + /// Your custom exception thrown when is a reference type and is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] + public static T MustNotBeNullReference( + [NotNull, ValidatedNotNull, NoEnumeration] + this T parameter, + Func exceptionFactory + ) + { + if (default(T) != null) + { + // If we end up here, parameter cannot be null +#pragma warning disable CS8777 // Parameter must have a non-null value when exiting. + return parameter; +#pragma warning restore CS8777 + } + + if (parameter is null) + { + Throw.CustomException(exceptionFactory); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeOneOf.cs b/Code/Light.GuardClauses/Check.MustNotBeOneOf.cs new file mode 100644 index 0000000..f4001b0 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeOneOf.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the value is not one of the specified items, or otherwise throws a . + /// + /// The value to be checked. + /// The items that must not contain the value. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when is equal to one of the specified . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("items:null => halt")] + // ReSharper disable once RedundantNullableFlowAttribute - the attribute has an effect, see Issue72NotNullAttribute tests + public static TItem MustNotBeOneOf( + this TItem parameter, + [NotNull] [ValidatedNotNull] IEnumerable items, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + // ReSharper disable PossibleMultipleEnumeration + if (parameter.IsOneOf(items.MustNotBeNull(nameof(items), message))) + { + Throw.ValueIsOneOf(parameter, items, parameterName, message); + } + + return parameter; + // ReSharper restore PossibleMultipleEnumeration + } + + /// + /// Ensures that the value is not one of the specified items, or otherwise throws your custom exception. + /// + /// The value to be checked. + /// The items that must not contain the value. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when is equal to one of the specified , or when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("items:null => halt")] + public static TItem MustNotBeOneOf( + this TItem parameter, + [NotNull] [ValidatedNotNull] TCollection items, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (items is null || parameter.IsOneOf(items)) + { + Throw.CustomException(exceptionFactory, parameter, items!); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeSameAs.cs b/Code/Light.GuardClauses/Check.MustNotBeSameAs.cs new file mode 100644 index 0000000..9b1af7f --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeSameAs.cs @@ -0,0 +1,53 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that and do not point to the same object instance, or otherwise + /// throws a . + /// + /// The first reference to be checked. + /// The second reference to be checked. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when both and point to the same object. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T? MustNotBeSameAs( + [NoEnumeration] this T? parameter, + [NoEnumeration] T? other, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where T : class + { + if (ReferenceEquals(parameter, other)) + { + Throw.SameObjectReference(parameter, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that and do not point to the same object instance, or otherwise + /// throws your custom exception. + /// + /// The first reference to be checked. + /// The second reference to be checked. + /// The delegate that creates your custom exception. is passed to this delegate. + /// Thrown when both and point to the same object. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T? MustNotBeSameAs([NoEnumeration] this T? parameter, T? other, Func exceptionFactory) where T : class + { + if (ReferenceEquals(parameter, other)) + { + Throw.CustomException(exceptionFactory, parameter); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotBeSubstringOf.cs b/Code/Light.GuardClauses/Check.MustNotBeSubstringOf.cs new file mode 100644 index 0000000..b098ae8 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotBeSubstringOf.cs @@ -0,0 +1,126 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string is not a substring of the specified other string, or otherwise throws a . + /// + /// The string to be checked. + /// The other string that must not contain . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when contains . + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustNotBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) + { + Throw.Substring(parameter, value, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is not a substring of the specified other string, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must not contain . + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when contains , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustNotBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || value.Contains(parameter)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + + return parameter; + } + + /// + /// Ensures that the string is not a substring of the specified other string, or otherwise throws a . + /// + /// The string to be checked. + /// The other string that must not contain . + /// One of the enumeration values that specifies the rules for the search. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when contains . + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustNotBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + value.MustNotBeNull(nameof(value), message); + parameter.MustNotBeNull(parameterName, message); + if (value.IndexOf(parameter, comparisonType) != -1) + { + Throw.Substring(parameter, value, comparisonType, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string is not a substring of the specified other string, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must not contain . + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when contains , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustNotBeSubstringOf( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || value.IndexOf(parameter, comparisonType) != -1) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotContain.cs b/Code/Light.GuardClauses/Check.MustNotContain.cs new file mode 100644 index 0000000..d9290ff --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotContain.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the collection does not contain the specified item, or otherwise throws an . + /// + /// The collection to be checked. + /// The item that must not be part of the collection. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when contains . + /// Thrown when is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustNotContain( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + TItem item, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) where TCollection : class, IEnumerable + { + if (parameter is ICollection collection) + { + if (collection.Contains(item)) + { + Throw.ExistingItem(parameter, item, parameterName, message); + } + + return parameter; + } + + if (parameter.MustNotBeNull(parameterName, message).Contains(item)) + { + Throw.ExistingItem(parameter, item, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the collection does not contain the specified item, or otherwise throws your custom exception. + /// + /// The collection to be checked. + /// The item that must not be part of the collection. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// Your custom exception thrown when contains . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static TCollection MustNotContain( + [NotNull] [ValidatedNotNull] this TCollection? parameter, + TItem item, + Func exceptionFactory + ) where TCollection : class, IEnumerable + { + if (parameter is ICollection collection) + { + if (collection.Contains(item)) + { + Throw.CustomException(exceptionFactory, parameter, item); + } + + return parameter; + } + + if (parameter is null || parameter.Contains(item)) + { + Throw.CustomException(exceptionFactory, parameter, item); + } + + return parameter; + } + + /// + /// Ensures that the string does not contain the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The string that must not be part of . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when contains . + /// Thrown when or is null. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustNotContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) + { + Throw.StringContains(parameter, value, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string does not contain the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The string that must not be part of . + /// The delegate that creates your custom exception (optional). and are passed to this delegate. + /// + /// Your custom exception thrown when contains , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustNotContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || parameter.Contains(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + + return parameter; + } + + /// + /// Ensures that the string does not contain the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The string that must not be part of . + /// One of the enumeration values that specifies the rules for the search. + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when contains . + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustNotContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).IndexOf( + value.MustNotBeNull(nameof(value), message), + comparisonType + ) >= + 0) + { + Throw.StringContains(parameter, value, comparisonType, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string does not contain the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The string that must not be part of . + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception (optional). , , and are passed to this delegate. + /// + /// Your custom exception thrown when contains , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] + public static string MustNotContain( + [NotNull] [ValidatedNotNull] this string? parameter, + string value, + StringComparison comparisonType, + Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off + if (parameter is null || value is null || parameter.IndexOf(value, comparisonType) >= 0) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotEndWith.cs b/Code/Light.GuardClauses/Check.MustNotEndWith.cs new file mode 100644 index 0000000..549a631 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotEndWith.cs @@ -0,0 +1,94 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- Caller might have NRTs turned off + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string does not end with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must not end with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when ends with . + /// Thrown when or is null. + /// Thrown when is not a valid value. + public static string MustNotEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).EndsWith(value, comparisonType)) + { + Throw.StringEndsWith(parameter, value, comparisonType, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the string does not end with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string must not end with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when ends with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.EndsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string does not end with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string must not end with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when ends with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotEndWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.EndsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustNotStartWith.cs b/Code/Light.GuardClauses/Check.MustNotStartWith.cs new file mode 100644 index 0000000..d4cc668 --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustNotStartWith.cs @@ -0,0 +1,96 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- Caller might have NRTs turned off + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string does not start with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string that must not start with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when starts with . + /// Thrown when or is null. + public static string MustNotStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] + string? parameterName = null, + string? message = null + ) + { + if (parameter.MustNotBeNull(parameterName, message).StartsWith(value, comparisonType)) + { + Throw.StringStartsWith(parameter, value, comparisonType, parameterName, message); + } + + return parameter; + } + + /// + /// Ensures that the string does not start with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must not start with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.StartsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string does not start with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string that must not start with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustNotStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || parameter.StartsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.MustStartWith.cs b/Code/Light.GuardClauses/Check.MustStartWith.cs new file mode 100644 index 0000000..ce3328e --- /dev/null +++ b/Code/Light.GuardClauses/Check.MustStartWith.cs @@ -0,0 +1,97 @@ +using System; +using System.Runtime.CompilerServices; +using JetBrains.Annotations; +using Light.GuardClauses.Exceptions; +using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; + +// ReSharper disable RedundantNullableFlowAttribute -- Caller might have NRTs turned off + +namespace Light.GuardClauses; + +public static partial class Check +{ + /// + /// Ensures that the string starts with the specified value, or otherwise throws a . + /// + /// The string to be checked. + /// The other string must start with. + /// One of the enumeration values that specifies the rules for the search (optional). The default value is . + /// The name of the parameter (optional). + /// The message that will be passed to the resulting exception (optional). + /// Thrown when does not start with . + /// Thrown when or is null. + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] + public static string MustStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType = StringComparison.CurrentCulture, + [CallerArgumentExpression("parameter")] string? parameterName = null, + string? message = null + ) + { + if (!parameter.MustNotBeNull(parameterName, message).StartsWith(value, comparisonType)) + { + Throw.StringDoesNotStartWith(parameter, value, comparisonType, parameterName, message); + } + return parameter; + } + + /// + /// Ensures that the string starts with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string must start with. + /// The delegate that creates your custom exception. and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !parameter.StartsWith(value)) + { + Throw.CustomException(exceptionFactory, parameter, value!); + } + return parameter; + } + + /// + /// Ensures that the string starts with the specified value, or otherwise throws your custom exception. + /// + /// The string to be checked. + /// The other string must start with. + /// One of the enumeration values that specifies the rules for the search. + /// The delegate that creates your custom exception. , , and are passed to this delegate. + /// + /// Your custom exception thrown when does not start with , + /// or when is null, + /// or when is null. + /// + /// Thrown when is not a valid value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] + public static string MustStartWith( + [NotNull, ValidatedNotNull] this string? parameter, + [NotNull, ValidatedNotNull] string value, + StringComparison comparisonType, + [NotNull, ValidatedNotNull] Func exceptionFactory + ) + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off + if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || !parameter.StartsWith(value, comparisonType)) + { + Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); + } + return parameter; + } +} diff --git a/Code/Light.GuardClauses/Check.StringAssertions.cs b/Code/Light.GuardClauses/Check.StringAssertions.cs deleted file mode 100644 index e8fff60..0000000 --- a/Code/Light.GuardClauses/Check.StringAssertions.cs +++ /dev/null @@ -1,1586 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Text.RegularExpressions; -using JetBrains.Annotations; -using Light.GuardClauses.Exceptions; -using Light.GuardClauses.FrameworkExtensions; -using System.Runtime.CompilerServices; -using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -namespace Light.GuardClauses; - -public static partial class Check -{ - /// - /// Checks if the specified string is null or empty. - /// - /// The string to be checked. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("=> false, string:notnull; => true, string:canbenull")] - public static bool IsNullOrEmpty([NotNullWhen(false)] this string? @string) => string.IsNullOrEmpty(@string); - - /// - /// Ensures that the specified string is not null or empty, or otherwise throws an or . - /// - /// The string to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is an empty string. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter is null) - Throw.ArgumentNull(parameterName, message); - if (parameter.Length == 0) - Throw.EmptyString(parameterName, message); - - return parameter; - } - - /// - /// Ensures that the specified string is not null or empty, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is an empty string or null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory:null => halt")] - public static string MustNotBeNullOrEmpty([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (parameter.IsNullOrEmpty()) - Throw.CustomException(exceptionFactory, parameter); - - return parameter; - } - - /// - /// Checks if the specified string is null, empty, or contains only white space. - /// - /// The string to be checked. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("=> false, string:notnull; => true, string:canbenull")] - public static bool IsNullOrWhiteSpace([NotNullWhen(false)] this string? @string) => string.IsNullOrWhiteSpace(@string); - - /// - /// Ensures that the specified string is not null, empty, or contains only white space, or otherwise throws an , an , or a . - /// - /// The string to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when contains only white space. - /// Thrown when is an empty string. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - parameter.MustNotBeNullOrEmpty(parameterName, message); - - foreach (var character in parameter) - { - if (!character.IsWhiteSpace()) - return parameter; - } - - Throw.WhiteSpaceString(parameter, parameterName, message); - return null; - } - - /// - /// Ensures that the specified string is not null, empty, or contains only white space, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is null, empty, or contains only white space. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; exceptionFactory: null => halt")] - public static string MustNotBeNullOrWhiteSpace([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (parameter.IsNullOrWhiteSpace()) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Checks if the specified character is a white space character. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsWhiteSpace(this char character) => char.IsWhiteSpace(character); - - /// - /// Checks if the specified character is a letter. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsLetter(this char character) => char.IsLetter(character); - - /// - /// Checks if the specified character is a letter or digit. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsLetterOrDigit(this char character) => char.IsLetterOrDigit(character); - - /// - /// Checks if the specified character is a digit. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsDigit(this char character) => char.IsDigit(character); - - /// - /// Ensures that the two strings are equal using the specified , or otherwise throws a . - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is not equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustBe(this string? parameter, string? other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!string.Equals(parameter, other, comparisonType)) - Throw.ValuesNotEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the two strings are equal using the specified , or otherwise throws your custom exception. - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is not equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustBe(this string? parameter, string? other, StringComparison comparisonType, Func exceptionFactory) - { - if (!string.Equals(parameter, other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other, comparisonType); - return parameter; - } - - /// - /// Ensures that the two strings are equal using the specified , or otherwise throws a . - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is not equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustBe(this string? parameter, string? other, StringComparisonType comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.Equals(other, comparisonType)) - Throw.ValuesNotEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the two strings are equal using the specified , or otherwise throws your custom exception. - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is not equal to . - /// Thrown when is not a valid value from the enum. - public static string? MustBe(this string? parameter, string? other, StringComparisonType comparisonType, Func exceptionFactory) - { - if (!parameter.Equals(other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other, comparisonType); - return parameter; - } - - /// - /// Ensures that the two strings are not equal using the specified , or otherwise throws a . - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustNotBe(this string? parameter, string? other, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (string.Equals(parameter, other, comparisonType)) - Throw.ValuesEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the two strings are not equal using the specified , or otherwise throws your custom exception. - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// Your custom exception thrown when is equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustNotBe(this string? parameter, string? other, StringComparison comparisonType, Func exceptionFactory) - { - if (string.Equals(parameter, other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other); - return parameter; - } - - /// - /// Ensures that the two strings are not equal using the specified , or otherwise throws a . - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustNotBe(this string? parameter, string? other, StringComparisonType comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.Equals(other, comparisonType)) - Throw.ValuesEqual(parameter, other, parameterName, message); - return parameter; - } - - /// - /// Ensures that the two strings are not equal using the specified , or otherwise throws your custom exception. - /// - /// The first string to be compared. - /// The second string to be compared. - /// The enum value specifying how the two strings should be compared. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// Your custom exception thrown when is equal to . - /// Thrown when is not a valid value from the enum. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string? MustNotBe(this string? parameter, string? other, StringComparisonType comparisonType, Func exceptionFactory) - { - if (parameter.Equals(other, comparisonType)) - Throw.CustomException(exceptionFactory, parameter, other, comparisonType); - return parameter; - } - - /// - /// Ensures that the string matches the specified regular expression, or otherwise throws a . - /// - /// The string to be checked. - /// The regular expression used for pattern matching. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not match the specified regular expression. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; regex:null => halt")] - public static string MustMatch([NotNull, ValidatedNotNull] this string? parameter, Regex regex, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!regex.MustNotBeNull(nameof(regex), message).IsMatch(parameter.MustNotBeNull(parameterName, message))) - Throw.StringDoesNotMatch(parameter, regex, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string matches the specified regular expression, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The regular expression used for pattern matching. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when does not match the specified regular expression, - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static string MustMatch([NotNull, ValidatedNotNull] this string? parameter, Regex regex, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || regex is null || !regex.IsMatch(parameter)) - Throw.CustomException(exceptionFactory, parameter, regex!); - return parameter; - } - - /// - /// Checks if the specified strings are equal, using the given comparison rules. - /// - /// The first string to compare. - /// The second string to compare. - /// One of the enumeration values that specifies the rules for the comparison. - /// True if the two strings are considered equal, else false. - /// Thrown when is no valid enum value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool Equals(this string? @string, string? value, StringComparisonType comparisonType) - { - if ((int) comparisonType < 6) - return string.Equals(@string, value, (StringComparison) comparisonType); - if (comparisonType == StringComparisonType.OrdinalIgnoreWhiteSpace) - return @string.EqualsOrdinalIgnoreWhiteSpace(value); - if (comparisonType == StringComparisonType.OrdinalIgnoreCaseIgnoreWhiteSpace) - return @string.EqualsOrdinalIgnoreCaseIgnoreWhiteSpace(value); - - Throw.EnumValueNotDefined(comparisonType, nameof(comparisonType)); - return false; - } - - /// - /// Ensures that the string contains the specified substring, or otherwise throws a . - /// - /// The string to be checked. - /// The substring that must be part of . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain . - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string? value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) - { - Throw.StringDoesNotContain(parameter, value, parameterName, message); - } - return parameter; - } - - /// - /// Ensures that the string contains the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The substring that must be part of . - /// The delegate that creates you custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when does not contain , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || !parameter.Contains(value)) - { - Throw.CustomException(exceptionFactory, parameter, value!); - } - return parameter; - } - - /// - /// Ensures that the string contains the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The substring that must be part of . - /// One of the enumeration values that specifies the rules for the search. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain . - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) < 0) - { - Throw.StringDoesNotContain(parameter, value, comparisonType, parameterName, message); - } - return parameter; - } - - /// - /// Ensures that the string contains the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The substring that must be part of . - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates you custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when does not contain , - /// or when is null, - /// or when is null. - /// - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || parameter.IndexOf(value, comparisonType) < 0) - { - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - } - return parameter; - } - - /// - /// Ensures that the string does not contain the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The string that must not be part of . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when contains . - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).Contains(value.MustNotBeNull(nameof(value), message))) - { - Throw.StringContains(parameter, value, parameterName, message); - } - return parameter; - } - - /// - /// Ensures that the string does not contain the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The string that must not be part of . - /// The delegate that creates your custom exception (optional). and are passed to this delegate. - /// - /// Your custom exception thrown when contains , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || parameter.Contains(value)) - Throw.CustomException(exceptionFactory, parameter, value!); - return parameter; - } - - /// - /// Ensures that the string does not contain the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The string that must not be part of . - /// One of the enumeration values that specifies the rules for the search. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when contains . - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).IndexOf(value.MustNotBeNull(nameof(value), message), comparisonType) >= 0) - Throw.StringContains(parameter, value, comparisonType, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string does not contain the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The string that must not be part of . - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception (optional). , , and are passed to this delegate. - /// - /// Your custom exception thrown when contains , - /// or when is null, - /// or when is null. - /// - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustNotContain([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || parameter.IndexOf(value, comparisonType) >= 0) - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - return parameter; - } - - /// - /// Checks if the string contains the specified value using the given comparison type. - /// - /// The string to be checked. - /// The other string. - /// One of the enumeration values that specifies the rules for the search. - /// True if contains , else false. - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("string:null => halt; value:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute - public static bool Contains([NotNull, ValidatedNotNull] this string @string, string value, StringComparison comparisonType) => - @string.MustNotBeNull(nameof(@string)).IndexOf(value.MustNotBeNull(nameof(value)), comparisonType) >= 0; - - /// - /// Checks if the string is a substring of the other string. - /// - /// The string to be checked. - /// The other string. - /// True if is a substring of , else false. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("value:null => halt; other:null => halt")] - // ReSharper disable RedundantNullableFlowAttribute - public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, [NotNull, ValidatedNotNull] string other) => - other.MustNotBeNull(nameof(other)).Contains(value); - // ReSharper restore RedundantNullableFlowAttribute - - /// - /// Checks if the string is a substring of the other string. - /// - /// The string to be checked. - /// The other string. - /// One of the enumeration values that specifies the rules for the search. - /// True if is a substring of , else false. - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("value:null => halt; other:null => halt")] - // ReSharper disable RedundantNullableFlowAttribute - public static bool IsSubstringOf([NotNull, ValidatedNotNull] this string value, [NotNull, ValidatedNotNull] string other, StringComparison comparisonType) => - other.MustNotBeNull(nameof(other)).IndexOf(value, comparisonType) != -1; - // ReSharper disable RedundantNullableFlowAttribute - - /// - /// Ensures that the string is a substring of the specified other string, or otherwise throws a . - /// - /// The string to be checked. - /// The other string that must contain . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain . - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) - Throw.NotSubstring(parameter, value, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is a substring of the specified other string, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string that must contain . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when does not contain , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || !value.Contains(parameter)) - Throw.CustomException(exceptionFactory, parameter, value!); - return parameter; - } - - /// - /// Ensures that the string is a substring of the specified other string, or otherwise throws a . - /// - /// The string to be checked. - /// The other string that must contain . - /// One of the enumeration values that specifies the rules for the search. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not contain . - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (value.MustNotBeNull(nameof(value), message).IndexOf(parameter.MustNotBeNull(parameterName, message), comparisonType) == -1) - Throw.NotSubstring(parameter, value, comparisonType, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is a substring of the specified other string, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string that must contain . - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when does not contain , - /// or when is null, - /// or when is null. - /// - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || value.IndexOf(parameter, comparisonType) == -1) - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - return parameter; - } - - /// - /// Ensures that the string is not a substring of the specified other string, or otherwise throws a . - /// - /// The string to be checked. - /// The other string that must not contain . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when contains . - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (value.MustNotBeNull(nameof(value), message).Contains(parameter.MustNotBeNull(parameterName, message))) - Throw.Substring(parameter, value, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is not a substring of the specified other string, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string that must not contain . - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when contains , - /// or when is null, - /// or when is null. - /// - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || value.Contains(parameter)) - Throw.CustomException(exceptionFactory, parameter, value!); - return parameter; - } - - /// - /// Ensures that the string is not a substring of the specified other string, or otherwise throws a . - /// - /// The string to be checked. - /// The other string that must not contain . - /// One of the enumeration values that specifies the rules for the search. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when contains . - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (value.MustNotBeNull(nameof(value), message).IndexOf(parameter.MustNotBeNull(parameterName, message), comparisonType) != -1) - Throw.Substring(parameter, value, comparisonType, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is not a substring of the specified other string, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string that must not contain . - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when contains , - /// or when is null, - /// or when is null. - /// - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustNotBeSubstringOf([NotNull, ValidatedNotNull] this string? parameter, string value, StringComparison comparisonType, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (parameter is null || value is null || value.IndexOf(parameter, comparisonType) != -1) - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - return parameter; - } - - /// - /// Ensures that the string starts with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must start with. - /// One of the enumeration values that specifies the rules for the search (optional). The default value is . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not start with . - /// Thrown when or is null. - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt")] - public static string MustStartWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType = StringComparison.CurrentCulture, - [CallerArgumentExpression("parameter")] string? parameterName = null, - string? message = null - ) - { - if (!parameter.MustNotBeNull(parameterName, message).StartsWith(value, comparisonType)) - { - Throw.StringDoesNotStartWith(parameter, value, comparisonType, parameterName, message); - } - return parameter; - } - - /// - /// Ensures that the string starts with the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string must start with. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when does not start with , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustStartWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || !parameter.StartsWith(value)) - { - Throw.CustomException(exceptionFactory, parameter, value!); - } - return parameter; - } - - /// - /// Ensures that the string starts with the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string must start with. - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when does not start with , - /// or when is null, - /// or when is null. - /// - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustStartWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || !comparisonType.IsValidEnumValue() || !parameter.StartsWith(value, comparisonType)) - { - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - } - return parameter; - } - - /// - /// Ensures that the string does not start with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string that must not start with. - /// One of the enumeration values that specifies the rules for the search (optional). The default value is . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when starts with . - /// Thrown when or is null. - public static string MustNotStartWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType = StringComparison.CurrentCulture, - [CallerArgumentExpression("parameter")] - string? parameterName = null, - string? message = null - ) - { - if (parameter.MustNotBeNull(parameterName, message).StartsWith(value, comparisonType)) - { - Throw.StringStartsWith(parameter, value, comparisonType, parameterName, message); - } - - return parameter; - } - - /// - /// Ensures that the string does not start with the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string that must not start with. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when does not start with , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustNotStartWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || parameter.StartsWith(value)) - { - Throw.CustomException(exceptionFactory, parameter, value!); - } - return parameter; - } - - /// - /// Ensures that the string does not start with the specified value, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The other string that must not start with. - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when does not start with , - /// or when is null, - /// or when is null. - /// - /// Thrown when is not a valid value. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustNotStartWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || parameter.StartsWith(value, comparisonType)) - { - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - } - return parameter; - } - - /// - /// Ensures that the string ends with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must end with. - /// One of the enumeration values that specifies the rules for the search (optional). The default value is . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when does not end with . - /// Thrown when or is null. - /// Thrown when is not a valid value. - public static string MustEndWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType = StringComparison.CurrentCulture, - [CallerArgumentExpression("parameter")] string? parameterName = null, - string? message = null - ) - { - if (!parameter.MustNotBeNull(parameterName, message).EndsWith(value, comparisonType)) - { - Throw.StringDoesNotEndWith(parameter, value, comparisonType, parameterName, message); - } - return parameter; - } - - /// - /// Ensures that the string ends with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must end with. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when does not end with , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustEndWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || !parameter.EndsWith(value)) - { - Throw.CustomException(exceptionFactory, parameter, value!); - } - return parameter; - } - - /// - /// Ensures that the string ends with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must end with. - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when does not end with , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustEndWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || !parameter.EndsWith(value, comparisonType)) - { - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - } - return parameter; - } - - /// - /// Ensures that the string does not end with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must not end with. - /// One of the enumeration values that specifies the rules for the search (optional). The default value is . - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when ends with . - /// Thrown when or is null. - /// Thrown when is not a valid value. - public static string MustNotEndWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType = StringComparison.CurrentCulture, - [CallerArgumentExpression("parameter")] string? parameterName = null, - string? message = null - ) - { - if (parameter.MustNotBeNull(parameterName, message).EndsWith(value, comparisonType)) - { - Throw.StringEndsWith(parameter, value, comparisonType, parameterName, message); - } - return parameter; - } - - /// - /// Ensures that the string does not end with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must not end with. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// - /// Your custom exception thrown when ends with , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustNotEndWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || parameter.EndsWith(value)) - { - Throw.CustomException(exceptionFactory, parameter, value!); - } - return parameter; - } - - /// - /// Ensures that the string does not end with the specified value, or otherwise throws a . - /// - /// The string to be checked. - /// The other string must not end with. - /// One of the enumeration values that specifies the rules for the search. - /// The delegate that creates your custom exception. , , and are passed to this delegate. - /// - /// Your custom exception thrown when ends with , - /// or when is null, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; value:null => halt; exceptionFactory:null => halt")] - public static string MustNotEndWith( - [NotNull, ValidatedNotNull] this string? parameter, - [NotNull, ValidatedNotNull] string value, - StringComparison comparisonType, - [NotNull, ValidatedNotNull] Func exceptionFactory - ) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract -- caller might have NRTs turned off - if (parameter is null || value is null || parameter.EndsWith(value, comparisonType)) - { - Throw.CustomException(exceptionFactory, parameter, value!, comparisonType); - } - return parameter; - } - - /// - /// Checks if the specified string is an email address using the default email regular expression - /// defined in . - /// - /// The string to be checked if it is an email address. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("emailAddress:null => false")] - public static bool IsEmailAddress([NotNullWhen(true)] this string? emailAddress) => - emailAddress != null && RegularExpressions.EmailRegex.IsMatch(emailAddress); - - /// - /// Checks if the specified string is an email address using the provided regular expression for validation. - /// - /// The string to be checked. - /// The regular expression that determines whether the input string is an email address. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("emailAddress:null => false; emailAddressPattern:null => halt")] - public static bool IsEmailAddress([NotNullWhen(true)] this string? emailAddress, Regex emailAddressPattern) => - emailAddress != null && emailAddressPattern.MustNotBeNull(nameof(emailAddressPattern)).IsMatch(emailAddress); - - /// - /// Ensures that the string is a valid email address using the default email regular expression - /// defined in , or otherwise throws an . - /// - /// The email address that will be validated. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is no valid email address. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress()) - Throw.InvalidEmailAddress(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is a valid email address using the default email regular expression - /// defined in , or otherwise throws your custom exception. - /// - /// The email address that will be validated. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is null or no valid email address. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (!parameter.IsEmailAddress()) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the string is a valid email address using the provided regular expression, - /// or otherwise throws an . - /// - /// The email address that will be validated. - /// The regular expression that determines if the input string is a valid email. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is no valid email address. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; emailAddressPattern:null => halt")] - public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, Regex emailAddressPattern, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).IsEmailAddress(emailAddressPattern)) - Throw.InvalidEmailAddress(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is a valid email address using the provided regular expression, - /// or otherwise throws your custom exception. - /// - /// The email address that will be validated. - /// The regular expression that determines if the input string is a valid email. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or no valid email address. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; emailAddressPattern:null => halt")] - public static string MustBeEmailAddress([NotNull, ValidatedNotNull] this string? parameter, Regex emailAddressPattern, Func exceptionFactory) - { - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (emailAddressPattern is null || !parameter.IsEmailAddress(emailAddressPattern)) - Throw.CustomException(exceptionFactory, parameter, emailAddressPattern!); - return parameter; - } - - /// - /// Ensures that the string is shorter than the specified length, or otherwise throws a . - /// - /// The string to be checked. - /// The length that the string must be shorter than. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has a length greater than or equal to . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThan([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).Length >= length) - Throw.StringNotShorterThan(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is shorter than the specified length, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The length that the string must be shorter than. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or when it has a length greater than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThan([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) - { - if (parameter is null || parameter.Length >= length) - Throw.CustomException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the string is shorter than or equal to the specified length, or otherwise throws a . - /// - /// The string to be checked. - /// The length that the string must be shorter than or equal to. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has a length greater than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).Length > length) - Throw.StringNotShorterThanOrEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is shorter than or equal to the specified length, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The length that the string must be shorter than or equal to. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or when it has a length greater than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeShorterThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) - { - if (parameter is null || parameter.Length > length) - Throw.CustomException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the string has the specified length, or otherwise throws a . - /// - /// The string to be checked. - /// The asserted length of the string. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has a length other than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLength([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).Length != length) - Throw.StringLengthNotEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string has the specified length, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The asserted length of the string. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or when it has a length other than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLength([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) - { - if (parameter is null || parameter.Length != length) - Throw.CustomException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the string is longer than the specified length, or otherwise throws a . - /// - /// The string to be checked. - /// The length that the string must be longer than. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has a length shorter than or equal to . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThan([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).Length <= length) - Throw.StringNotLongerThan(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is longer than the specified length, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The length that the string must be longer than. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or when it has a length shorter than or equal to . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThan([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) - { - if (parameter is null || parameter.Length <= length) - Throw.CustomException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the string is longer than or equal to the specified length, or otherwise throws a . - /// - /// The string to be checked. - /// The length that the string must be longer than or equal to. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when has a length shorter than . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).Length < length) - Throw.StringNotLongerThanOrEqualTo(parameter, length, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is longer than or equal to the specified length, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The length that the string must be longer than or equal to. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or when it has a length shorter than . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeLongerThanOrEqualTo([NotNull, ValidatedNotNull] this string? parameter, int length, Func exceptionFactory) - { - if (parameter is null || parameter.Length < length) - Throw.CustomException(exceptionFactory, parameter, length); - return parameter; - } - - /// - /// Ensures that the string's length is within the specified range, or otherwise throws a . - /// - /// The string to be checked. - /// The range where the string'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 with the specified . - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLengthIn([NotNull, ValidatedNotNull] this string? parameter, Range range, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!range.IsValueWithinRange(parameter.MustNotBeNull(parameterName, message).Length)) - Throw.StringLengthNotInRange(parameter, range, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string's length is within the specified range, or otherwise throws your custom exception. - /// - /// The string to be checked. - /// The range where the string's length must be in-between. - /// The delegate that creates your custom exception. and are passed to this delegate. - /// Your custom exception thrown when is null or its length is not within the specified range. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustHaveLengthIn([NotNull, ValidatedNotNull] this string? parameter, Range range, Func, Exception> exceptionFactory) - { - if (parameter is null || !range.IsValueWithinRange(parameter.Length)) - Throw.CustomException(exceptionFactory, parameter, range); - return parameter; - } - - /// - /// Checks if the string is either "\n" or "\r\n". This is done independently of the current value of . - /// - /// The string to be checked. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("=> false, parameter:canbenull; => true, parameter:notnull")] - public static bool IsNewLine([NotNullWhen(true)] this string? parameter) => parameter == "\n" || parameter == "\r\n"; - - /// - /// Ensures that the string is either "\n" or "\r\n", or otherwise throws a . This is done independently of the current value of . - /// - /// The string to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is not equal to "\n" or "\r\n". - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeNewLine([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).IsNewLine()) - Throw.NotNewLine(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is either "\n" or "\r\n", or otherwise throws your custom exception. This is done independently of the current value of . - /// - /// The string to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is not equal to "\n" or "\r\n". - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeNewLine([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (!parameter.IsNewLine()) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Checks if the specified string is trimmed, i.e. it does not start or end with - /// white space characters. Inputting an empty string will return true. When null is passed, - /// you can control the return value with which will - /// return true by default. - /// - /// The string to be checked. - /// - /// The value indicating whether true or false should be returned from this method when the - /// is null. The default value is true. - /// - /// - /// True if the is trimmed, else false. An empty string will result in true. - /// You can control the return value with when the - /// is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsTrimmed(this string? parameter, bool regardNullAsTrimmed = true) => - parameter is null ? regardNullAsTrimmed : parameter.AsSpan().IsTrimmed(); - - /// - /// Checks if the specified character span is trimmed, i.e. it does not start or end with - /// white space characters. Inputting an empty span will return true. - /// - /// The character span to be checked. - /// True if the is trimmed, else false. An empty span will result in true. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsTrimmed(this ReadOnlySpan parameter) => - parameter.Length == 0 || - !parameter[0].IsWhiteSpace() && - !parameter[parameter.Length - 1].IsWhiteSpace(); - - - /// - /// Ensures that the string is not null and trimmed, or otherwise throws a . - /// Empty strings are regarded as trimmed. - /// - /// The string to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// - /// Thrown when is not trimmed, i.e. they start or end with white space characters. - /// Empty strings are regarded as trimmed. - /// - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmed([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).IsTrimmed()) - Throw.NotTrimmed(parameter, parameterName, message); - return parameter; - - } - - /// - /// Ensures that the string is not null and trimmed, or otherwise throws your custom exception. - /// Empty strings are regarded as trimmed. - /// - /// The string to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is null or not trimmed. Empty strings are regarded as trimmed. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmed([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (parameter is null || !parameter.AsSpan().IsTrimmed()) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Checks if the specified string is trimmed at the start, i.e. it does not start with - /// white space characters. Inputting an empty string will return true. - /// - /// The string to be checked. - /// - /// The value indicating whether true or false should be returned from this method when the - /// is null. The default value is true. - /// - /// - /// True if the is trimmed at the start, else false. - /// An empty string will result in true. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsTrimmedAtStart(this string? parameter, bool regardNullAsTrimmed = true) => - parameter is null ? regardNullAsTrimmed : parameter.AsSpan().IsTrimmedAtStart(); - - /// - /// Checks if the specified character span is trimmed at the start, i.e. it does not start with - /// white space characters. Inputting an empty span will return true. - /// - /// The character span to be checked. - /// - /// True if the is trimmed at the start, else false. - /// An empty span will result in true. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsTrimmedAtStart(this ReadOnlySpan parameter) => - parameter.Length == 0 || !parameter[0].IsWhiteSpace(); - - /// - /// Ensures that the string is not null and trimmed at the start, or otherwise throws a . - /// Empty strings are regarded as trimmed. - /// - /// The string to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// - /// Thrown when is not trimmed at the start, i.e. they start with white space characters. - /// Empty strings are regarded as trimmed. - /// - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtStart([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtStart()) - Throw.NotTrimmedAtStart(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is not null and trimmed at the start, or otherwise throws your custom exception. - /// Empty strings are regarded as trimmed. - /// - /// The string to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is null or not trimmed at the start. Empty strings are regarded as trimmed. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtStart([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (parameter is null || !parameter.AsSpan().IsTrimmedAtStart()) - Throw.CustomException(exceptionFactory, parameter); - 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. - /// - /// The string to be checked. - /// - /// The value indicating whether true or false should be returned from this method when the - /// is null. The default value is true. - /// - /// - /// True if the is trimmed at the start, else false. - /// An empty string will result in true. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsTrimmedAtEnd(this string? parameter, bool regardNullAsTrimmed = true) => - parameter is null ? regardNullAsTrimmed : parameter.AsSpan().IsTrimmedAtEnd(); - - /// - /// Checks if the specified character span is trimmed at the end, i.e. it does not end with - /// white space characters. Inputting an empty span will return true. - /// - /// The character span to be checked. - /// - /// True if the is trimmed at the end, else false. - /// An empty span will result in true. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsTrimmedAtEnd(this ReadOnlySpan parameter) => - parameter.Length == 0 || !parameter[parameter.Length - 1].IsWhiteSpace(); - - /// - /// Ensures that the string is not null and trimmed at the end, or otherwise throws a . - /// Empty strings are regarded as trimmed. - /// - /// The string to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// - /// Thrown when is not trimmed at the end, i.e. they end with white space characters. - /// Empty strings are regarded as trimmed. - /// - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtEnd([NotNull, ValidatedNotNull] this string? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (!parameter.MustNotBeNull(parameterName, message).IsTrimmedAtEnd()) - Throw.NotTrimmedAtEnd(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the string is not null and trimmed at the end, or otherwise throws your custom exception. - /// Empty strings are regarded as trimmed. - /// - /// The string to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is null or not trimmed at the end. Empty strings are regarded as trimmed. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static string MustBeTrimmedAtEnd([NotNull, ValidatedNotNull] this string? parameter, Func exceptionFactory) - { - if (parameter is null || !parameter.AsSpan().IsTrimmedAtEnd()) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.TypeAssertions.cs b/Code/Light.GuardClauses/Check.TypeAssertions.cs deleted file mode 100644 index 3fd8a0d..0000000 --- a/Code/Light.GuardClauses/Check.TypeAssertions.cs +++ /dev/null @@ -1,332 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using JetBrains.Annotations; -#if NET8_0 -using System.Diagnostics.CodeAnalysis; -#endif -using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -namespace Light.GuardClauses; - -public static partial class Check -{ - /// - /// Checks if the two specified types are equivalent. This is true when both types are equal or - /// when one type is a constructed generic type and the other type is the corresponding generic type definition. - /// - /// The first type to be checked. - /// The other type to be checked. - /// - /// True if both types are null, or if both are equal, or if one type - /// is a constructed generic type and the other one is the corresponding generic type definition, else false. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool IsEquivalentTypeTo(this Type? type, Type? other) => - ReferenceEquals(type, other) || - !(type is null) && - !(other is null) && - (type == other || - type.IsConstructedGenericType != other.IsConstructedGenericType && - CheckTypeEquivalency(type, other)); - - private static bool CheckTypeEquivalency(Type type, Type other) - { - if (type.IsConstructedGenericType) - return type.GetGenericTypeDefinition() == other; - return other.GetGenericTypeDefinition() == type; - } - - /// - /// Checks if the type implements the specified interface type. Internally, this method uses - /// so that constructed generic types and their corresponding generic type definitions are regarded as equal. - /// - /// The type to be checked. - /// The interface type that should implement. - /// Thrown when or is null. - [ContractAnnotation("type:null => halt; interfaceType:null => halt")] - public static bool Implements( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type interfaceType - // ReSharper restore RedundantNullableFlowAttribute - ) - { - type.MustNotBeNull(); - interfaceType.MustNotBeNull(); - - var implementedInterfaces = type.GetInterfaces(); - for (var i = 0; i < implementedInterfaces.Length; ++i) - { - if (interfaceType.IsEquivalentTypeTo(implementedInterfaces[i])) - return true; - } - - return false; - } - - /// - /// Checks if the type implements the specified interface type. This overload uses the specified - /// to compare the interface types. - /// - /// The type to be checked. - /// The interface type that should implement. - /// The equality comparer used to compare the interface types. - /// Thrown when , or , or is null. - [ContractAnnotation("type:null => halt; interfaceType:null => halt; typeComparer:null => halt")] - public static bool Implements( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type interfaceType, - [NotNull, ValidatedNotNull] IEqualityComparer typeComparer - // ReSharper restore RedundantNullableFlowAttribute - ) - { - type.MustNotBeNull(); - interfaceType.MustNotBeNull(); - typeComparer.MustNotBeNull(); - - var implementedInterfaces = type.GetInterfaces(); - for (var i = 0; i < implementedInterfaces.Length; ++i) - { - if (typeComparer.Equals(implementedInterfaces[i], interfaceType)) - return true; - } - - return false; - } - - /// - /// Checks if the given is equal to the specified or if it implements it. Internally, this - /// method uses so that constructed generic types and their corresponding generic type definitions are regarded as equal. - /// - /// The type to be checked. - /// The type that is equivalent to or the interface type that implements. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; otherType:null => halt")] - public static bool IsOrImplements( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type otherType) => - // ReSharper restore RedundantNullableFlowAttribute - type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.Implements(otherType); - - /// - /// Checks if the given is equal to the specified or if it implements it. This overload uses the specified - /// to compare the types. - /// - /// , - /// The type to be checked. - /// The type that is equivalent to or the interface type that implements. - /// The equality comparer used to compare the interface types. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; otherType:null => halt")] - public static bool IsOrImplements( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type otherType, - [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => - // ReSharper restore RedundantNullableFlowAttribute - typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type.MustNotBeNull(nameof(type)), otherType.MustNotBeNull(nameof(otherType))) || type.Implements(otherType, typeComparer); - - /// - /// 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. - /// - /// The type info to be checked. - /// The base class that should derive from. - /// Thrown when or is null. - [ContractAnnotation("type:null => halt; baseClass:null => halt")] - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static bool DerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type baseClass) - // ReSharper restore RedundantNullableFlowAttribute - { - baseClass.MustNotBeNull(nameof(baseClass)); - - var currentBaseType = type.MustNotBeNull(nameof(type)).BaseType; - while (currentBaseType != null) - { - if (currentBaseType.IsEquivalentTypeTo(baseClass)) - return true; - - currentBaseType = currentBaseType.BaseType; - } - - return false; - } - - /// - /// Checks if the specified type derives from the other type. This overload uses the specified - /// to compare the types. - /// - /// The type info to be checked. - /// The base class that should derive from. - /// The equality comparer used to compare the types. - /// Thrown when , or , or is null. - [ContractAnnotation("type:null => halt; baseClass:null => halt; typeComparer:null => halt")] - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static bool DerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type baseClass, [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) - // ReSharper restore RedundantNullableFlowAttribute - { - baseClass.MustNotBeNull(nameof(baseClass)); - typeComparer.MustNotBeNull(nameof(typeComparer)); - - var currentBaseType = type.MustNotBeNull(nameof(type)).BaseType; - while (currentBaseType != null) - { - if (typeComparer.Equals(currentBaseType, baseClass)) - return true; - - currentBaseType = currentBaseType.BaseType; - } - - return false; - } - - /// - /// Checks if the given is equal to the specified or if it derives from it. Internally, this - /// method uses so that constructed generic types and their corresponding generic type definitions are regarded as equal. - /// - /// The type to be checked. - /// The type that is equivalent to or the base class type where derives from. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; otherType:null => halt")] - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static bool IsOrDerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type otherType) => - // ReSharper restore RedundantNullableFlowAttribute - type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.DerivesFrom(otherType); - - /// - /// Checks if the given is equal to the specified or if it derives from it. This overload uses the specified - /// to compare the types. - /// - /// The type to be checked. - /// The type that is equivalent to or the base class type where derives from. - /// The equality comparer used to compare the types. - /// Thrown when , or , or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; otherType:null => halt; typeComparer:null => halt")] - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static bool IsOrDerivesFrom([NotNull, ValidatedNotNull] this Type type, [NotNull, ValidatedNotNull] Type otherType, [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => - // ReSharper restore RedundantNullableFlowAttribute - typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type, otherType.MustNotBeNull(nameof(otherType))) || type.DerivesFrom(otherType, typeComparer); - - - /// - /// Checks if the given type derives from the specified base class or interface type. Internally, this method uses - /// so that constructed generic types and their corresponding generic type definitions are regarded as equal. - /// - /// The type to be checked. - /// The type describing an interface or base class that should derive from or implement. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; baseClassOrInterfaceType:null => halt")] - public static bool InheritsFrom( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type baseClassOrInterfaceType) => - // ReSharper restore RedundantNullableFlowAttribute - baseClassOrInterfaceType.MustNotBeNull(nameof(baseClassOrInterfaceType)) - .IsInterface ? - type.Implements(baseClassOrInterfaceType) : - type.DerivesFrom(baseClassOrInterfaceType); - - /// - /// Checks if the given type derives from the specified base class or interface type. This overload uses the specified - /// to compare the types. - /// - /// The type to be checked. - /// The type describing an interface or base class that should derive from or implement. - /// The equality comparer used to compare the types. - /// Thrown when , or , or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; baseClassOrInterfaceType:null => halt; typeComparer:null => halt")] - public static bool InheritsFrom( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type baseClassOrInterfaceType, - [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => - // ReSharper restore RedundantNullableFlowAttribute - baseClassOrInterfaceType.MustNotBeNull(nameof(baseClassOrInterfaceType)) - .IsInterface ? - type.Implements(baseClassOrInterfaceType, typeComparer) : - type.DerivesFrom(baseClassOrInterfaceType, typeComparer); - - /// - /// Checks if the given is equal to the specified or if it derives from it or implements it. - /// Internally, this method uses so that constructed generic types and their corresponding generic type definitions - /// are regarded as equal. - /// - /// The type to be checked. - /// The type that is equivalent to or the base class type where derives from. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; otherType:null => halt")] - public static bool IsOrInheritsFrom( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type otherType) => - // ReSharper restore RedundantNullableFlowAttribute - type.IsEquivalentTypeTo(otherType.MustNotBeNull(nameof(otherType))) || type.InheritsFrom(otherType); - - - /// - /// Checks if the given is equal to the specified or if it derives from it or implements it. - /// This overload uses the specified to compare the types. - /// - /// The type to be checked. - /// The type that is equivalent to or the base class type where derives from. - /// The equality comparer used to compare the types. - /// Thrown when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt; otherType:null => halt; typeComparer:null => halt")] - public static bool IsOrInheritsFrom( -#if NET8_0 - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] -#endif - // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - [NotNull, ValidatedNotNull] this Type type, - [NotNull, ValidatedNotNull] Type otherType, - [NotNull, ValidatedNotNull] IEqualityComparer typeComparer) => - // ReSharper restore RedundantNullableFlowAttribute - typeComparer.MustNotBeNull(nameof(typeComparer)).Equals(type, otherType.MustNotBeNull(nameof(otherType))) || type.InheritsFrom(otherType, typeComparer); - - - /// - /// Checks if the given is a generic type that has open generic parameters, - /// but is no generic type definition. - /// - /// The type to be checked. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("type:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static bool IsOpenConstructedGenericType([NotNull, ValidatedNotNull] this Type type) => - type.MustNotBeNull(nameof(type)).IsGenericType && - type.ContainsGenericParameters && - type.IsGenericTypeDefinition == false; -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.UriAssertions.cs b/Code/Light.GuardClauses/Check.UriAssertions.cs deleted file mode 100644 index a45d6c8..0000000 --- a/Code/Light.GuardClauses/Check.UriAssertions.cs +++ /dev/null @@ -1,288 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using JetBrains.Annotations; -using Light.GuardClauses.Exceptions; -using System.Runtime.CompilerServices; -using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; - -namespace Light.GuardClauses; - -public static partial class Check -{ - /// - /// Ensures that the specified URI is an absolute one, or otherwise throws a . - /// - /// The URI to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is not an absolute URI. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeAbsoluteUri([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri == false) - Throw.MustBeAbsoluteUri(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified URI is an absolute one, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The delegate that creates the exception to be thrown. is passed to this delegate. - /// Your custom exception thrown when is not an absolute URI, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeAbsoluteUri([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) - { - if (parameter is null || parameter.IsAbsoluteUri == false) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the specified URI is a relative one, or otherwise throws an . - /// - /// The URI to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when is an absolute URI. - /// Thrown when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustNotBeNull(parameterName, message).IsAbsoluteUri) - Throw.MustBeRelativeUri(parameter, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified URI is a relative one, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The delegate that creates your custom exception. is passed to this delegate. - /// Your custom exception thrown when is an absolute URI, or when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeRelativeUri([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) - { - if (parameter is null || parameter.IsAbsoluteUri) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the has the specified scheme, or otherwise throws an . - /// - /// The URI to be checked. - /// The scheme that the URI should have. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when uses a different scheme than the specified one. - /// Thrown when is relative and thus has no scheme. - /// Throw when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (string.Equals(parameter.MustBeAbsoluteUri(parameterName, message).Scheme, scheme) == false) - Throw.UriMustHaveScheme(parameter, scheme, parameterName, message); - return parameter; - } - - /// - /// Ensures that the has the specified scheme, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The scheme that the URI should have. - /// The delegate that creates the exception to be thrown. is passed to this delegate. - /// - /// Your custom exception thrown when uses a different scheme than the specified one, - /// or when is a relative URI, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, Func exceptionFactory) - { - if (string.Equals(parameter.MustBeAbsoluteUri(exceptionFactory).Scheme, scheme) == false) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the has the specified scheme, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The scheme that the URI should have. - /// The delegate that creates the exception to be thrown. and are passed to this delegate. - /// - /// Your custom exception thrown when uses a different scheme than the specified one, - /// or when is a relative URI, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveScheme([NotNull, ValidatedNotNull] this Uri? parameter, string scheme, Func exceptionFactory) - { - if (parameter is null || !parameter.IsAbsoluteUri || parameter.Scheme.Equals(scheme) == false) - Throw.CustomException(exceptionFactory, parameter, scheme); - return parameter; - } - - /// - /// Ensures that the specified URI has the "https" scheme, or otherwise throws an . - /// - /// The URI to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when uses a different scheme than "https". - /// Thrown when is relative and thus has no scheme. - /// Throw when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => parameter.MustHaveScheme("https", parameterName, message); - - /// - /// Ensures that the specified URI has the "https" scheme, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The delegate that creates the exception to be thrown. is passed to this delegate. - /// - /// Your custom exception thrown when uses a different scheme than "https", - /// or when is a relative URI, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) => parameter.MustHaveScheme("https", exceptionFactory); - - /// - /// Ensures that the specified URI has the "http" scheme, or otherwise throws an . - /// - /// The URI to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when uses a different scheme than "http". - /// Thrown when is relative and thus has no scheme. - /// Throw when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) => parameter.MustHaveScheme("http", parameterName, message); - - /// - /// Ensures that the specified URI has the "http" scheme, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The delegate that creates the exception to be thrown. is passed to this delegate. - /// - /// Your custom exception thrown when uses a different scheme than "http", - /// or when is a relative URI, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) => parameter.MustHaveScheme("http", exceptionFactory); - - /// - /// Ensures that the specified URI has the "http" or "https" scheme, or otherwise throws an . - /// - /// The URI to be checked. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when uses a different scheme than "http" or "https". - /// Thrown when is relative and thus has no scheme. - /// Throw when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - if (parameter.MustBeAbsoluteUri(parameterName, message).Scheme.Equals("https") == false && parameter.Scheme.Equals("http") == false) - Throw.UriMustHaveOneSchemeOf(parameter, new[] { "https", "http" }, parameterName, message); - return parameter; - } - - /// - /// Ensures that the specified URI has the "http" or "https" scheme, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// The delegate that creates the exception to be thrown. is passed to this delegate. - /// - /// Your custom exception thrown when uses a different scheme than "http" or "https", - /// or when is a relative URI, - /// or when is null. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustBeHttpOrHttpsUrl([NotNull, ValidatedNotNull] this Uri? parameter, Func exceptionFactory) - { - if (parameter.MustBeAbsoluteUri(exceptionFactory).Scheme.Equals("https") == false && parameter.Scheme.Equals("http") == false) - Throw.CustomException(exceptionFactory, parameter); - return parameter; - } - - /// - /// Ensures that the URI has one of the specified schemes, or otherwise throws an . - /// - /// The URI to be checked. - /// One of these strings must be equal to the scheme of the URI. - /// The name of the parameter (optional). - /// The message that will be passed to the resulting exception (optional). - /// Thrown when the scheme is not equal to one of the specified schemes. - /// Thrown when is relative and thus has no scheme. - /// Throw when or is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull; schemes:null => halt")] - public static Uri MustHaveOneSchemeOf([NotNull, ValidatedNotNull] this Uri? parameter, IEnumerable schemes, [CallerArgumentExpression("parameter")] string? parameterName = null, string? message = null) - { - // ReSharper disable PossibleMultipleEnumeration - parameter.MustBeAbsoluteUri(parameterName, message); - - if (schemes is ICollection collection) - { - if (!collection.Contains(parameter.Scheme)) - Throw.UriMustHaveOneSchemeOf(parameter, schemes, parameterName, message); - return parameter; - } - - if (!schemes.MustNotBeNull(nameof(schemes), message).Contains(parameter.Scheme)) - Throw.UriMustHaveOneSchemeOf(parameter, schemes, parameterName, message); - return parameter; - // ReSharper restore PossibleMultipleEnumeration - } - - /// - /// Ensures that the URI has one of the specified schemes, or otherwise throws your custom exception. - /// - /// The URI to be checked. - /// One of these strings must be equal to the scheme of the URI. - /// The delegate that creates your custom exception. - /// - /// Your custom exception thrown when the scheme is not equal to one of the specified schemes, - /// or when is a relative URI, - /// or when is null. - /// - /// Throw when is null. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [ContractAnnotation("parameter:null => halt; parameter:notnull => notnull")] - public static Uri MustHaveOneSchemeOf([NotNull, ValidatedNotNull] this Uri? parameter, TCollection schemes, Func exceptionFactory) where TCollection : class, IEnumerable - { - if (parameter is null || !parameter.IsAbsoluteUri) - Throw.CustomException(exceptionFactory, parameter, schemes); - - if (schemes is ICollection collection) - { - if (!collection.Contains(parameter.Scheme)) - Throw.CustomException(exceptionFactory, parameter, schemes); - return parameter; - } - - // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract - caller might have NRTs turned off - if (schemes is null || !schemes.Contains(parameter.Scheme)) - Throw.CustomException(exceptionFactory, parameter, schemes!); - return parameter; - } -} \ No newline at end of file diff --git a/Code/Light.GuardClauses/Check.cs b/Code/Light.GuardClauses/Check.cs new file mode 100644 index 0000000..ac14024 --- /dev/null +++ b/Code/Light.GuardClauses/Check.cs @@ -0,0 +1,6 @@ +namespace Light.GuardClauses; + +/// +/// The class provides access to all assertions of Light.GuardClauses. +/// +public static partial class Check; diff --git a/Code/Light.GuardClauses/EnumInfo.cs b/Code/Light.GuardClauses/EnumInfo.cs index d10ad44..49232e9 100644 --- a/Code/Light.GuardClauses/EnumInfo.cs +++ b/Code/Light.GuardClauses/EnumInfo.cs @@ -21,7 +21,7 @@ public static class EnumInfo where T : struct, Enum typeof(T).GetCustomAttribute(Types.FlagsAttributeType) != null; /// - /// Gets the flags pattern when is true. If the enum is not a flags enum, then 0UL is returned. + /// Gets the flags pattern when is true. If the enum is not a flags enum, then 0UL is returned. /// public static readonly ulong FlagsPattern; @@ -40,10 +40,12 @@ static EnumInfo() #else EnumConstantsArray = (T[]) Enum.GetValues(typeof(T)); #endif - EnumConstants = new (EnumConstantsArray); + EnumConstants = new ReadOnlyMemory(EnumConstantsArray); if (!IsFlagsEnum) + { return; + } for (var i = 0; i < EnumConstantsArray.Length; ++i) { @@ -63,8 +65,12 @@ private static bool IsValidValue(T parameter) { var comparer = EqualityComparer.Default; for (var i = 0; i < EnumConstantsArray.Length; ++i) + { if (comparer.Equals(EnumConstantsArray[i], parameter)) + { return true; + } + } return false; } @@ -90,12 +96,11 @@ private static ulong ConvertToUInt64(T value) case 8: return Unsafe.As(ref value); default: ThrowUnknownEnumSize(); - return default; + return 0UL; } } - private static void ThrowUnknownEnumSize() - { - throw new InvalidOperationException($"The enum type \"{typeof(T)}\" has an unknown size of {EnumSize}. This means that the underlying enum type is not one of the supported ones."); - } -} \ No newline at end of file + private static void ThrowUnknownEnumSize() => throw new InvalidOperationException( + $"The enum type \"{typeof(T)}\" has an unknown size of {EnumSize}. This means that the underlying enum type is not one of the supported ones." + ); +} diff --git a/Code/Light.GuardClauses/EquivalentTypeComparer.cs b/Code/Light.GuardClauses/EquivalentTypeComparer.cs index 02784ac..6123f9e 100644 --- a/Code/Light.GuardClauses/EquivalentTypeComparer.cs +++ b/Code/Light.GuardClauses/EquivalentTypeComparer.cs @@ -15,7 +15,7 @@ public sealed class EquivalentTypeComparer : IEqualityComparer /// /// Gets a singleton instance of the equality comparer. /// - public static readonly EquivalentTypeComparer Instance = new EquivalentTypeComparer(); + public static readonly EquivalentTypeComparer Instance = new (); /// /// Checks if the two types are equivalent (using ). @@ -35,8 +35,8 @@ public sealed class EquivalentTypeComparer : IEqualityComparer /// The type whose hash code is requested. [MethodImpl(MethodImplOptions.AggressiveInlining)] public int GetHashCode(Type type) => - // ReSharper disable once ConditionIsAlwaysTrueOrFalse + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract type is null ? 0 : type.IsConstructedGenericType ? type.GetGenericTypeDefinition().GetHashCode() : type.GetHashCode(); -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs index f204458..9ecd452 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/EnumerableExtensions.cs @@ -2,8 +2,8 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using JetBrains.Annotations; using System.Runtime.CompilerServices; +using JetBrains.Annotations; using Light.GuardClauses.Exceptions; using NotNullAttribute = System.Diagnostics.CodeAnalysis.NotNullAttribute; @@ -25,7 +25,7 @@ public static class EnumerableExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull")] // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable source) => + public static IList AsList([NotNull] [ValidatedNotNull] this IEnumerable source) => source as IList ?? source.ToList(); /// @@ -39,9 +39,13 @@ public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable /// Thrown when or is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull; createCollection:null => halt")] - // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable source, Func, IList> createCollection) => - source as IList ?? createCollection.MustNotBeNull(nameof(createCollection))(source.MustNotBeNull(nameof(source))); + public static IList AsList( + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull] [ValidatedNotNull] this IEnumerable source, + Func, IList> createCollection + ) => + source as IList ?? + createCollection.MustNotBeNull(nameof(createCollection))(source.MustNotBeNull(nameof(source))); /// /// Tries to downcast the specified enumerable to an array, or creates a new array with the specified items. @@ -53,7 +57,8 @@ public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull")] // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static T[] AsArray([NotNull, ValidatedNotNull] this IEnumerable source) => source as T[] ?? source.ToArray(); + public static T[] AsArray([NotNull] [ValidatedNotNull] this IEnumerable source) => + source as T[] ?? source.ToArray(); /// /// Performs the action on each item of the specified enumerable. If the enumerable contains items that are null, this @@ -65,8 +70,12 @@ public static IList AsList([NotNull, ValidatedNotNull] this IEnumerable /// The value indicating whether this method should throw a when any of the items is null (optional). Defaults to true. /// Thrown when or is null. /// Thrown when contains a value that is null and is set to true. - // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static IEnumerable ForEach([NotNull, ValidatedNotNull] this IEnumerable enumerable, Action action, bool throwWhenItemIsNull = true) + public static IEnumerable ForEach( + // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests + [NotNull] [ValidatedNotNull] this IEnumerable enumerable, + Action action, + bool throwWhenItemIsNull = true + ) { // ReSharper disable PossibleMultipleEnumeration action.MustNotBeNull(nameof(action)); @@ -79,7 +88,14 @@ public static IEnumerable ForEach([NotNull, ValidatedNotNull] this IEnumer var item = list[i]; if (item is null) { - if (throwWhenItemIsNull) throw new CollectionException(nameof(enumerable), $"The collection contains null at index {i}."); + if (throwWhenItemIsNull) + { + throw new CollectionException( + nameof(enumerable), + $"The collection contains null at index {i}." + ); + } + continue; } @@ -92,7 +108,14 @@ public static IEnumerable ForEach([NotNull, ValidatedNotNull] this IEnumer { if (item is null) { - if (throwWhenItemIsNull) throw new CollectionException(nameof(enumerable), $"The collection contains null at index {i}."); + if (throwWhenItemIsNull) + { + throw new CollectionException( + nameof(enumerable), + $"The collection contains null at index {i}." + ); + } + ++i; continue; } @@ -117,7 +140,7 @@ public static IEnumerable ForEach([NotNull, ValidatedNotNull] this IEnumer [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull")] // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] this IEnumerable source) => + public static IReadOnlyList AsReadOnlyList([NotNull] [ValidatedNotNull] this IEnumerable source) => source as IReadOnlyList ?? source.ToList(); /// @@ -132,8 +155,12 @@ public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] thi [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("source:null => halt; source:notnull => notnull; createCollection:null => halt")] // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] this IEnumerable source, [NotNull, ValidatedNotNull] Func, IReadOnlyList> createCollection) => - source as IReadOnlyList ?? createCollection.MustNotBeNull(nameof(createCollection))(source.MustNotBeNull(nameof(source))); + public static IReadOnlyList AsReadOnlyList( + [NotNull] [ValidatedNotNull] this IEnumerable source, + [NotNull] [ValidatedNotNull] Func, IReadOnlyList> createCollection + ) => + source as IReadOnlyList ?? + createCollection.MustNotBeNull(nameof(createCollection))(source.MustNotBeNull(nameof(source))); // ReSharper restore RedundantNullableFlowAttribute @@ -141,16 +168,21 @@ public static IReadOnlyList AsReadOnlyList([NotNull, ValidatedNotNull] thi /// Gets the count of the specified enumerable. /// /// The enumerable whose count should be determined. - /// Thrown when is null. + /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] // ReSharper disable once RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static int Count([NotNull, ValidatedNotNull] this IEnumerable enumerable) + public static int Count([NotNull] [ValidatedNotNull] this IEnumerable enumerable) { if (enumerable is ICollection collection) + { return collection.Count; + } + if (enumerable is string @string) + { return @string.Length; + } return DetermineCountViaEnumerating(enumerable); } @@ -159,37 +191,54 @@ public static int Count([NotNull, ValidatedNotNull] this IEnumerable enumerable) /// Gets the count of the specified enumerable. /// /// The enumerable whose count should be determined. - /// The name of the parameter that is passed to the (optional). - /// The message that is passed to the (optional). - /// Thrown when is null. + /// The name of the parameter that is passed to the (optional). + /// The message that is passed to the (optional). + /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] - public static int Count([NotNull, ValidatedNotNull] this IEnumerable? enumerable, string? parameterName, string? message) + public static int Count( + [NotNull] [ValidatedNotNull] this IEnumerable? enumerable, + string? parameterName, + string? message + ) { if (enumerable is ICollection collection) + { return collection.Count; + } + if (enumerable is string @string) + { return @string.Length; + } return DetermineCountViaEnumerating(enumerable, parameterName, message); } - + /// /// Gets the count of the specified enumerable. /// /// The enumerable whose count should be determined. - /// Thrown when is null. + /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] // ReSharper disable RedundantNullableFlowAttribute -- NotNull has an effect, see Issue72NotNullAttributeTests - public static int GetCount([NotNull, ValidatedNotNull] this IEnumerable enumerable) + public static int GetCount([NotNull] [ValidatedNotNull] this IEnumerable enumerable) { if (enumerable is ICollection collection) + { return collection.Count; + } + if (enumerable is string @string) + { return @string.Length; + } + if (TryGetCollectionOfTCount(enumerable, out var count)) + { return count; + } return DetermineCountViaEnumerating(enumerable); } @@ -198,19 +247,31 @@ public static int GetCount([NotNull, ValidatedNotNull] this IEnumerable en /// Gets the count of the specified enumerable. /// /// The enumerable whose count should be determined. - /// The name of the parameter that is passed to the (optional). - /// The message that is passed to the (optional). - /// Thrown when is null. + /// The name of the parameter that is passed to the (optional). + /// The message that is passed to the (optional). + /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("enumerable:null => halt")] - public static int GetCount([NotNull, ValidatedNotNull] this IEnumerable enumerable, string? parameterName, string? message = null) + public static int GetCount( + [NotNull] [ValidatedNotNull] this IEnumerable enumerable, + string? parameterName, + string? message = null + ) { if (enumerable is ICollection collection) + { return collection.Count; + } + if (enumerable is string @string) + { return @string.Length; + } + if (TryGetCollectionOfTCount(enumerable, out var count)) + { return count; + } return DetermineCountViaEnumerating(enumerable, parameterName, message); } @@ -222,6 +283,7 @@ private static bool TryGetCollectionOfTCount([NoEnumeration] this IEnumerable count = collectionOfT.Count; return true; } + if (enumerable is IReadOnlyCollection readOnlyCollection) { count = readOnlyCollection.Count; @@ -237,24 +299,36 @@ private static int DetermineCountViaEnumerating(IEnumerable? enumerable) var count = 0; var enumerator = enumerable.MustNotBeNull(nameof(enumerable)).GetEnumerator(); while (enumerator.MoveNext()) + { count++; + } + if (enumerator is IDisposable disposable) { disposable.Dispose(); } + return count; } - private static int DetermineCountViaEnumerating([NotNull] IEnumerable? enumerable, string? parameterName, string? message) + private static int DetermineCountViaEnumerating( + [NotNull] IEnumerable? enumerable, + string? parameterName, + string? message + ) { var count = 0; var enumerator = enumerable.MustNotBeNull(parameterName, message).GetEnumerator(); while (enumerator.MoveNext()) + { count++; + } + if (enumerator is IDisposable disposable) { disposable.Dispose(); } + return count; } @@ -264,9 +338,11 @@ internal static bool ContainsViaForeach(this IEnumerable items, TI foreach (var i in items) { if (equalityComparer.Equals(i, item)) + { return true; + } } return false; } -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs index c695215..28ff16c 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/ExpressionExtensions.cs @@ -20,14 +20,21 @@ public static class ExpressionExtensions /// /// Throw when the is not of the shape "object => object.Property". /// - // ReSharper disable once RedundantNullableFlowAttribute - NotNull is not redundant, see Issue72NotNullAttributeTests - public static PropertyInfo ExtractProperty([NotNull, ValidatedNotNull] this Expression> expression) + public static PropertyInfo ExtractProperty( + // ReSharper disable once RedundantNullableFlowAttribute - NotNull is not redundant, see Issue72NotNullAttributeTests + [NotNull] [ValidatedNotNull] this Expression> expression + ) { expression.MustNotBeNull(nameof(expression)); var memberExpression = expression.Body as MemberExpression; if (!(memberExpression?.Member is PropertyInfo propertyInfo)) - throw new ArgumentException("The specified expression is not valid. Please use an expression like the following one: o => o.Property", nameof(expression)); + { + throw new ArgumentException( + "The specified expression is not valid. Please use an expression like the following one: o => o.Property", + nameof(expression) + ); + } return propertyInfo; } @@ -42,15 +49,22 @@ public static PropertyInfo ExtractProperty([NotNull, ValidatedNotN /// /// Throw when the is not of the shape "object => object.Field". /// - // ReSharper disable once RedundantNullableFlowAttribute - NotNull is not redundant, see Issue72NotNullAttributeTests - public static FieldInfo ExtractField([NotNull, ValidatedNotNull] this Expression> expression) + public static FieldInfo ExtractField( + // ReSharper disable once RedundantNullableFlowAttribute - NotNull is not redundant, see Issue72NotNullAttributeTests + [NotNull] [ValidatedNotNull] this Expression> expression + ) { expression.MustNotBeNull(nameof(expression)); var memberExpression = expression.Body as MemberExpression; if (!(memberExpression?.Member is FieldInfo fieldInfo)) - throw new ArgumentException("The specified expression is not valid. Please use an expression like the following one: o => o.Field", nameof(expression)); + { + throw new ArgumentException( + "The specified expression is not valid. Please use an expression like the following one: o => o.Field", + nameof(expression) + ); + } return fieldInfo; } -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHash.cs b/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHash.cs index 2e36ae8..92a2880 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHash.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHash.cs @@ -83,7 +83,14 @@ public static int CreateHashCode(T1 value1, T2 value2, T3 va /// Creates a hash code from the six specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -99,7 +106,15 @@ public static int CreateHashCode(T1 value1, T2 value2, T /// Creates a hash code from the seven specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -116,7 +131,16 @@ public static int CreateHashCode(T1 value1, T2 value /// Creates a hash code from the eight specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -134,7 +158,17 @@ public static int CreateHashCode(T1 value1, T2 v /// Creates a hash code from the nine specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -153,7 +187,18 @@ public static int CreateHashCode(T1 value1, /// Creates a hash code from the ten specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -173,7 +218,19 @@ public static int CreateHashCode(T1 val /// Creates a hash code from the eleven specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10, T11 value11) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -194,7 +251,20 @@ public static int CreateHashCode(T /// Creates a hash code from the eleven specified values. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10, T11 value11, T12 value12) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -216,7 +286,21 @@ public static int CreateHashCode [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10, T11 value11, T12 value12, T13 value13) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -239,7 +323,22 @@ public static int CreateHashCode [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10, T11 value11, T12 value12, T13 value13, T14 value14) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -263,7 +362,23 @@ public static int CreateHashCode [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10, T11 value11, T12 value12, T13 value13, T14 value14, T15 value15) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -288,7 +403,24 @@ public static int CreateHashCode [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int CreateHashCode(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8, T9 value9, T10 value10, T11 value11, T12 value12, T13 value13, T14 value14, T15 value15, T16 value16) + public static int CreateHashCode( + T1 value1, + T2 value2, + T3 value3, + T4 value4, + T5 value5, + T6 value6, + T7 value7, + T8 value8, + T9 value9, + T10 value10, + T11 value11, + T12 value12, + T13 value13, + T14 value14, + T15 value15, + T16 value16 + ) { var hash = FirstPrime; CombineIntoHash(ref hash, value1); @@ -315,5 +447,6 @@ public static int CreateHashCodehash = unchecked(hash * SecondPrime + value?.GetHashCode() ?? 0);. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void CombineIntoHash(ref int hash, T value) => hash = unchecked(hash * SecondPrime + value?.GetHashCode() ?? 0); -} \ No newline at end of file + public static void CombineIntoHash(ref int hash, T value) => + hash = unchecked(hash * SecondPrime + value?.GetHashCode() ?? 0); +} diff --git a/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHashBuilder.cs b/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHashBuilder.cs index 7bb438f..c411eeb 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHashBuilder.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/MultiplyAddHashBuilder.cs @@ -3,10 +3,10 @@ namespace Light.GuardClauses.FrameworkExtensions; /// -/// Represents a builder for the algorithm that does not allocate. +/// Represents a builder for the algorithm that does not allocate. /// Should only be used in cases where the overload for sixteen values is not enough or a dedicated /// initial hash must be provided (e.g. for test reasons). -/// Instantiate the builder with the method. You have to instantiate a new builder +/// Instantiate the builder with the method. You have to instantiate a new builder /// for each hash code that you want to calculate. /// public struct MultiplyAddHashBuilder @@ -17,7 +17,7 @@ public struct MultiplyAddHashBuilder private MultiplyAddHashBuilder(int initialHash) => _hash = initialHash; /// - /// Combines the given value into the hash using the method. + /// Combines the given value into the hash using the method. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public MultiplyAddHashBuilder CombineIntoHash(T value) @@ -33,9 +33,8 @@ public MultiplyAddHashBuilder CombineIntoHash(T value) public int BuildHash() => _hash; /// - /// Initializes a new instance of with the specified initial hash. + /// Initializes a new instance of with the specified initial hash. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static MultiplyAddHashBuilder Create(int initialHash = MultiplyAddHash.FirstPrime) => new MultiplyAddHashBuilder(initialHash); - -} \ No newline at end of file + public static MultiplyAddHashBuilder Create(int initialHash = MultiplyAddHash.FirstPrime) => new (initialHash); +} diff --git a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs index 10f3b7c..96901a9 100644 --- a/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs +++ b/Code/Light.GuardClauses/FrameworkExtensions/TextExtensions.cs @@ -35,36 +35,71 @@ public static class TextExtensions typeof(bool), typeof(double), typeof(decimal), - typeof(float) + typeof(float), ] ); private static bool IsUnquotedType() { if (typeof(T) == typeof(int)) + { return true; + } + if (typeof(T) == typeof(long)) + { return true; + } + if (typeof(T) == typeof(short)) + { return true; + } + if (typeof(T) == typeof(sbyte)) + { return true; + } + if (typeof(T) == typeof(uint)) + { return true; + } + if (typeof(T) == typeof(ulong)) + { return true; + } + if (typeof(T) == typeof(ushort)) + { return true; + } + if (typeof(T) == typeof(byte)) + { return true; + } + if (typeof(T) == typeof(bool)) + { return true; + } + if (typeof(T) == typeof(double)) + { return true; + } + if (typeof(T) == typeof(decimal)) + { return true; + } + if (typeof(T) == typeof(float)) + { return true; + } return false; } @@ -77,7 +112,8 @@ private static bool IsUnquotedType() /// The text that is returned when is null (defaults to "null"). [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("=> notnull")] - public static string ToStringOrNull(this T value, string nullText = "null") => value?.ToStringRepresentation() ?? nullText; + public static string ToStringOrNull(this T value, string nullText = "null") => + value?.ToStringRepresentation() ?? nullText; /// /// Returns the string representation of . This is done by calling . If the type of @@ -85,13 +121,15 @@ private static bool IsUnquotedType() /// /// The value whose string representation is requested. [ContractAnnotation("value:null => halt; value:notnull => notnull")] - public static string? ToStringRepresentation([NotNull, ValidatedNotNull] this T value) + public static string? ToStringRepresentation([NotNull] [ValidatedNotNull] this T value) { value.MustNotBeNullReference(nameof(value)); var content = value.ToString(); if (IsUnquotedType() || content.IsNullOrEmpty()) + { return content; + } // ReSharper disable UseIndexFromEndExpression -- not possible in netstandard2.0 if (content.Length <= 126) @@ -123,7 +161,12 @@ private static bool IsUnquotedType() [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; items:null => halt; stringBuilder:notnull => notnull")] // ReSharper disable RedundantNullableFlowAttribute - public static StringBuilder AppendCollectionContent([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] IEnumerable items, string headerLine = "Content of the collection:", bool finishWithNewLine = true) => + public static StringBuilder AppendCollectionContent( + [NotNull] [ValidatedNotNull] this StringBuilder stringBuilder, + [NotNull] [ValidatedNotNull] IEnumerable items, + string headerLine = "Content of the collection:", + bool finishWithNewLine = true + ) => stringBuilder.MustNotBeNull(nameof(stringBuilder)) .AppendLine(headerLine) .AppendItemsWithNewLine(items, finishWithNewLine: finishWithNewLine); @@ -139,7 +182,12 @@ public static StringBuilder AppendCollectionContent([NotNull, ValidatedNotNul /// Thrown when or is null. [ContractAnnotation("stringBuilder:null => halt; items:null => halt; stringBuilder:notnull => notnull")] // ReSharper disable RedundantNullableFlowAttribute - public static StringBuilder AppendItems([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] IEnumerable items, string itemSeparator = ", ", string emptyCollectionText = "empty collection") + public static StringBuilder AppendItems( + [NotNull] [ValidatedNotNull] this StringBuilder stringBuilder, + [NotNull] [ValidatedNotNull] IEnumerable items, + string itemSeparator = ", ", + string emptyCollectionText = "empty collection" + ) // ReSharper restore RedundantNullableFlowAttribute { stringBuilder.MustNotBeNull(nameof(stringBuilder)); @@ -148,15 +196,22 @@ public static StringBuilder AppendItems([NotNull, ValidatedNotNull] this Stri var currentIndex = 0; var itemsCount = list.Count; if (itemsCount == 0) + { return stringBuilder.Append(emptyCollectionText); + } while (true) { stringBuilder.Append(list[currentIndex].ToStringOrNull()); if (currentIndex < itemsCount - 1) + { stringBuilder.Append(itemSeparator); + } else + { return stringBuilder; + } + ++currentIndex; } } @@ -172,7 +227,12 @@ public static StringBuilder AppendItems([NotNull, ValidatedNotNull] this Stri [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; items:null => halt; stringBuilder:notnull => notnull")] // ReSharper disable RedundantNullableFlowAttribute - public static StringBuilder AppendItemsWithNewLine([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] IEnumerable items, string emptyCollectionText = "empty collection", bool finishWithNewLine = true) => + public static StringBuilder AppendItemsWithNewLine( + [NotNull] [ValidatedNotNull] this StringBuilder stringBuilder, + [NotNull] [ValidatedNotNull] IEnumerable items, + string emptyCollectionText = "empty collection", + bool finishWithNewLine = true + ) => stringBuilder.AppendItems(items, DefaultNewLineSeparator, emptyCollectionText) .AppendLineIf(finishWithNewLine); // ReSharper restore RedundantNullableFlowAttribute @@ -186,11 +246,18 @@ public static StringBuilder AppendItemsWithNewLine([NotNull, ValidatedNotNull /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; stringBuilder:notnull => notnull")] - // ReSharper disable once RedundantNullableFlowAttribute - public static StringBuilder AppendIf([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, bool condition, string value) + public static StringBuilder AppendIf( + // ReSharper disable once RedundantNullableFlowAttribute + [NotNull] [ValidatedNotNull] this StringBuilder stringBuilder, + bool condition, + string value + ) { if (condition) + { stringBuilder.MustNotBeNull(nameof(stringBuilder)).Append(value); + } + return stringBuilder; } @@ -203,11 +270,18 @@ public static StringBuilder AppendIf([NotNull, ValidatedNotNull] this StringBuil /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] [ContractAnnotation("stringBuilder:null => halt; stringBuilder:notnull => notnull")] - // ReSharper disable once RedundantNullableFlowAttribute - public static StringBuilder AppendLineIf([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, bool condition, string value = "") + public static StringBuilder AppendLineIf( + // ReSharper disable once RedundantNullableFlowAttribute + [NotNull] [ValidatedNotNull] this StringBuilder stringBuilder, + bool condition, + string value = "" + ) { if (condition) + { stringBuilder.MustNotBeNull(nameof(stringBuilder)).AppendLine(value); + } + return stringBuilder; } @@ -217,7 +291,10 @@ public static StringBuilder AppendLineIf([NotNull, ValidatedNotNull] this String /// /// Thrown when any parameter is null. // ReSharper disable RedundantNullableFlowAttribute - public static StringBuilder AppendExceptionMessages([NotNull, ValidatedNotNull] this StringBuilder stringBuilder, [NotNull, ValidatedNotNull] Exception exception) + public static StringBuilder AppendExceptionMessages( + [NotNull] [ValidatedNotNull] this StringBuilder stringBuilder, + [NotNull] [ValidatedNotNull] Exception exception + ) // ReSharper restore RedundantNullableFlowAttribute { stringBuilder.MustNotBeNull(nameof(stringBuilder)); @@ -228,7 +305,9 @@ public static StringBuilder AppendExceptionMessages([NotNull, ValidatedNotNull] // ReSharper disable once PossibleNullReferenceException stringBuilder.AppendLine(exception.Message); if (exception.InnerException is null) + { return stringBuilder; + } stringBuilder.AppendLine(); exception = exception.InnerException; @@ -241,7 +320,7 @@ public static StringBuilder AppendExceptionMessages([NotNull, ValidatedNotNull] /// /// Thrown when is null. // ReSharper disable once RedundantNullableFlowAttribute - public static string GetAllExceptionMessages([NotNull, ValidatedNotNull] this Exception exception) => + public static string GetAllExceptionMessages([NotNull] [ValidatedNotNull] this Exception exception) => new StringBuilder().AppendExceptionMessages(exception).ToString(); /// @@ -251,13 +330,19 @@ public static string GetAllExceptionMessages([NotNull, ValidatedNotNull] this Ex public static bool EqualsOrdinalIgnoreWhiteSpace(this string? x, string? y) { if (ReferenceEquals(x, y)) + { return true; + } if (x is null || y is null) + { return false; + } if (x.Length == 0) + { return y.Length == 0; + } var indexX = 0; var indexY = 0; @@ -271,7 +356,9 @@ public static bool EqualsOrdinalIgnoreWhiteSpace(this string? x, string? y) (wasYSuccessful = y.TryAdvanceToNextNonWhiteSpaceCharacter(ref indexY))) { if (x[indexX++] != y[indexY++]) + { return false; + } } return wasXSuccessful == wasYSuccessful; @@ -284,13 +371,19 @@ public static bool EqualsOrdinalIgnoreWhiteSpace(this string? x, string? y) public static bool EqualsOrdinalIgnoreCaseIgnoreWhiteSpace(this string? x, string? y) { if (ReferenceEquals(x, y)) + { return true; + } if (x is null || y is null) + { return false; + } if (x.Length == 0) + { return y.Length == 0; + } var indexX = 0; var indexY = 0; @@ -304,7 +397,9 @@ public static bool EqualsOrdinalIgnoreCaseIgnoreWhiteSpace(this string? x, strin (wasYSuccessful = y.TryAdvanceToNextNonWhiteSpaceCharacter(ref indexY))) { if (char.ToLowerInvariant(x[indexX++]) != char.ToLowerInvariant(y[indexY++])) + { return false; + } } return wasXSuccessful == wasYSuccessful; @@ -315,11 +410,13 @@ private static bool TryAdvanceToNextNonWhiteSpaceCharacter(this string @string, while (currentIndex < @string.Length) { if (!char.IsWhiteSpace(@string[currentIndex])) + { return true; + } ++currentIndex; } return false; } -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/OrdinalIgnoreCaseIgnoreWhiteSpaceComparer.cs b/Code/Light.GuardClauses/OrdinalIgnoreCaseIgnoreWhiteSpaceComparer.cs index 5ed7ed6..fc1f2d7 100644 --- a/Code/Light.GuardClauses/OrdinalIgnoreCaseIgnoreWhiteSpaceComparer.cs +++ b/Code/Light.GuardClauses/OrdinalIgnoreCaseIgnoreWhiteSpaceComparer.cs @@ -5,7 +5,7 @@ namespace Light.GuardClauses; /// -/// Represents an that compares strings using the +/// Represents an that compares strings using the /// ordinal sort rules, ignoring the case and the white space characters. /// public sealed class OrdinalIgnoreCaseIgnoreWhiteSpaceComparer : IEqualityComparer @@ -14,7 +14,7 @@ public sealed class OrdinalIgnoreCaseIgnoreWhiteSpaceComparer : IEqualityCompare /// Checks if the two strings are equal using ordinal sorting rules as well as ignoring the case and /// the white space of the provided strings. /// - /// Thrown when or are null. + /// Thrown when or are null. public bool Equals(string? x, string? y) { x.MustNotBeNull(nameof(x)); @@ -27,7 +27,7 @@ public bool Equals(string? x, string? y) /// Gets the hash code for the specified string. The hash code is created only from the non-white space characters /// which are interpreted as case-insensitive. /// - /// Thrown when is null. + /// Thrown when is null. public int GetHashCode(string @string) { @string.MustNotBeNull(nameof(@string)); @@ -37,9 +37,11 @@ public int GetHashCode(string @string) foreach (var character in @string) { if (!character.IsWhiteSpace()) + { hashBuilder.CombineIntoHash(char.ToLowerInvariant(character)); + } } return hashBuilder.BuildHash(); } -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/OrdinalIgnoreWhiteSpaceComparer.cs b/Code/Light.GuardClauses/OrdinalIgnoreWhiteSpaceComparer.cs index 07cb57c..7a150e6 100644 --- a/Code/Light.GuardClauses/OrdinalIgnoreWhiteSpaceComparer.cs +++ b/Code/Light.GuardClauses/OrdinalIgnoreWhiteSpaceComparer.cs @@ -5,7 +5,7 @@ namespace Light.GuardClauses; /// -/// Represents an that compares strings using the +/// Represents an that compares strings using the /// ordinal sort rules and ignoring the white space characters. /// public sealed class OrdinalIgnoreWhiteSpaceComparer : IEqualityComparer @@ -14,7 +14,7 @@ public sealed class OrdinalIgnoreWhiteSpaceComparer : IEqualityComparer /// Checks if the two strings are equal using ordinal sorting rules as well as ignoring the white space /// of the provided strings. /// - /// Thrown when or are null. + /// Thrown when or are null. public bool Equals(string? x, string? y) { x.MustNotBeNull(nameof(x)); @@ -26,7 +26,7 @@ public bool Equals(string? x, string? y) /// /// Gets the hash code for the specified string. The hash code is created only from the non-white space characters. /// - /// Thrown when is null. + /// Thrown when is null. public int GetHashCode(string @string) { @string.MustNotBeNull(nameof(@string)); @@ -35,9 +35,11 @@ public int GetHashCode(string @string) foreach (var character in @string) { if (!character.IsWhiteSpace()) + { hashCodeBuilder.CombineIntoHash(character); + } } return hashCodeBuilder.BuildHash(); } -} \ No newline at end of file +} diff --git a/Code/Light.GuardClauses/Range.cs b/Code/Light.GuardClauses/Range.cs index 623df25..8ef1f30 100644 --- a/Code/Light.GuardClauses/Range.cs +++ b/Code/Light.GuardClauses/Range.cs @@ -1,8 +1,8 @@ using System; using System.Collections; using System.Collections.Generic; -using Light.GuardClauses.FrameworkExtensions; using System.Runtime.CompilerServices; +using Light.GuardClauses.FrameworkExtensions; namespace Light.GuardClauses; @@ -62,7 +62,7 @@ public Range(T from, T to, bool isFromInclusive = true, bool isToInclusive = tru /// True if value is within range, otherwise false. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsValueWithinRange(T value) => - value.MustNotBeNullReference(nameof(value)).CompareTo(From) >= _expectedLowerBoundaryResult && + value.MustNotBeNullReference(nameof(value)).CompareTo(From) >= _expectedLowerBoundaryResult && value.CompareTo(To) <= _expectedUpperBoundaryResult; /// @@ -72,7 +72,7 @@ public bool IsValueWithinRange(T value) => /// The value that indicates the inclusive lower boundary of the resulting range. /// A value you can use to fluently define the upper boundary of a new range. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static RangeFromInfo FromInclusive(T value) => new RangeFromInfo(value, true); + public static RangeFromInfo FromInclusive(T value) => new (value, true); /// /// Use this method to create a range in a fluent style using method chaining. @@ -81,7 +81,7 @@ public bool IsValueWithinRange(T value) => /// The value that indicates the exclusive lower boundary of the resulting range. /// A value you can use to fluently define the upper boundary of a new range. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static RangeFromInfo FromExclusive(T value) => new RangeFromInfo(value, false); + public static RangeFromInfo FromExclusive(T value) => new (value, false); /// /// The nested can be used to fluently create a . @@ -113,7 +113,7 @@ public RangeFromInfo(T from, bool isFromInclusive) /// Thrown when is less than the lower boundary value. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Range ToExclusive(T value) => new Range(_from, value, _isFromInclusive, false); + public Range ToExclusive(T value) => new (_from, value, _isFromInclusive, false); /// /// Use this method to create a range in a fluent style using method chaining. @@ -125,15 +125,14 @@ public RangeFromInfo(T from, bool isFromInclusive) /// Thrown when is less than the lower boundary value. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Range ToInclusive(T value) => new Range(_from, value, _isFromInclusive); + public Range ToInclusive(T value) => new (_from, value, _isFromInclusive); } /// - public override string ToString() => - $"Range from {CreateRangeDescriptionText()}"; + public override string ToString() => $"Range from {CreateRangeDescriptionText()}"; /// - /// Returns either "inclusive" or "exclusive", depending on whether is true or false. + /// Returns either "inclusive" or "exclusive", depending on whether is true or false. /// public string LowerBoundaryText { @@ -142,7 +141,7 @@ public string LowerBoundaryText } /// - /// Returns either "inclusive" or "exclusive", depending on whether is true or false. + /// Returns either "inclusive" or "exclusive", depending on whether is true or false. /// public string UpperBoundaryText { @@ -164,7 +163,10 @@ public bool Equals(Range other) { if (IsFromInclusive != other.IsFromInclusive || IsToInclusive != other.IsToInclusive) + { return false; + } + var comparer = EqualityComparer.Default; return comparer.Equals(From, other.From) && comparer.Equals(To, other.To); @@ -173,7 +175,11 @@ public bool Equals(Range other) /// public override bool Equals(object? other) { - if (other is null) return false; + if (other is null) + { + return false; + } + return other is Range range && Equals(range); } @@ -194,7 +200,7 @@ public override bool Equals(object? other) } /// -/// Provides methods to simplify the creation of instances. +/// Provides methods to simplify the creation of instances. /// public static class Range { @@ -243,11 +249,11 @@ public static class Range /// The count of this enumerable will be used to create the index range. Please ensure that this enumerable /// is actually a collection, not a lazy enumerable. /// - /// Thrown when is null. + /// Thrown when is null. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(IEnumerable enumerable) => - new (0, enumerable.Count(), isFromInclusive: true, isToInclusive: false); - + new (0, enumerable.Count(), true, false); + /// /// Creates a range for the specified enumerable that encompasses all valid indexes. /// @@ -255,10 +261,10 @@ public static Range For(IEnumerable enumerable) => /// The count of this enumerable will be used to create the index range. Please ensure that this enumerable /// is actually a collection, not a lazy enumerable. /// - /// Thrown when is null. + /// Thrown when is null. public static Range For(IEnumerable enumerable) => - new (0, enumerable.GetCount(), isFromInclusive: true, isToInclusive: false); - + new (0, enumerable.GetCount(), true, false); + /// /// Creates a range for the specified span that encompasses all valid indexes. /// @@ -267,8 +273,8 @@ public static Range For(IEnumerable enumerable) => /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(ReadOnlySpan span) => - new (0, span.Length, isFromInclusive: true, isToInclusive: false); - + new (0, span.Length, true, false); + /// /// Creates a range for the specified span that encompasses all valid indexes. /// @@ -277,7 +283,7 @@ public static Range For(ReadOnlySpan span) => /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(Span span) => - new (0 , span.Length, isFromInclusive: true, isToInclusive: false); + new (0, span.Length, true, false); /// /// Creates a range for the specified memory that encompasses all valid indexes. @@ -287,8 +293,8 @@ public static Range For(Span span) => /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(Memory memory) => - new (0, memory.Length, isFromInclusive: true, isToInclusive: false); - + new (0, memory.Length, true, false); + /// /// Creates a range for the specified memory that encompasses all valid indexes. /// @@ -297,8 +303,8 @@ public static Range For(Memory memory) => /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(ReadOnlyMemory memory) => - new (0, memory.Length, isFromInclusive: true, isToInclusive: false); - + new (0, memory.Length, true, false); + /// /// Creates a range for the specified memory that encompasses all valid indexes. /// @@ -307,5 +313,5 @@ public static Range For(ReadOnlyMemory memory) => /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Range For(ArraySegment segment) => - new (0, segment.Count, isFromInclusive: true, isToInclusive: false); + new (0, segment.Count, true, false); } diff --git a/Code/Light.GuardClauses/RegularExpressions.cs b/Code/Light.GuardClauses/RegularExpressions.cs index 62ff37a..0a40137 100644 --- a/Code/Light.GuardClauses/RegularExpressions.cs +++ b/Code/Light.GuardClauses/RegularExpressions.cs @@ -12,7 +12,8 @@ public static class RegularExpressions /// This pattern is based on https://www.rhyous.com/2010/06/15/csharp-email-regular-expression/ and /// was modified to satisfy all tests of https://blogs.msdn.microsoft.com/testing123/2009/02/06/email-address-test-cases/. /// - public static readonly Regex EmailRegex = new Regex( + public static readonly Regex EmailRegex = new ( @"^[\w!#$%&'*+\-/=?\^_`{|}~]+(\.[\w!#$%&'*+\-/=?\^_`{|}~]+)*@((((\w+\-?)+\.)+[a-zA-Z]{2,4})|(([0-9]{1,3}\.){3}[0-9]{1,3}))$", - RegexOptions.CultureInvariant | RegexOptions.ECMAScript); -} \ No newline at end of file + RegexOptions.CultureInvariant | RegexOptions.ECMAScript + ); +} diff --git a/Code/Light.GuardClauses/SpanDelegates.cs b/Code/Light.GuardClauses/SpanDelegates.cs index 2e3e7d5..68b1776 100644 --- a/Code/Light.GuardClauses/SpanDelegates.cs +++ b/Code/Light.GuardClauses/SpanDelegates.cs @@ -10,4 +10,4 @@ namespace Light.GuardClauses; /// /// Represents a delegate that receives a read-only span and a value as parameters and that produces an exception. /// -public delegate Exception ReadOnlySpanExceptionFactory(ReadOnlySpan span, T value); \ No newline at end of file +public delegate Exception ReadOnlySpanExceptionFactory(ReadOnlySpan span, T value); diff --git a/Code/Light.GuardClauses/StringComparisonType.cs b/Code/Light.GuardClauses/StringComparisonType.cs index f127498..93768c8 100644 --- a/Code/Light.GuardClauses/StringComparisonType.cs +++ b/Code/Light.GuardClauses/StringComparisonType.cs @@ -4,9 +4,9 @@ /// Specifies the culture, case , and sort rules when comparing strings. /// /// -/// This enum is en extension of , adding +/// This enum is en extension of , adding /// capabilities to ignore white space when making string equality comparisons. -/// See the when +/// See the when /// you want to compare in such a way. /// public enum StringComparisonType @@ -54,5 +54,5 @@ public enum StringComparisonType /// Compare strings using ordinal sort rules, ignoring the case and ignoring the /// white space characters of the strings being compared. /// - OrdinalIgnoreCaseIgnoreWhiteSpace = 7 -} \ No newline at end of file + OrdinalIgnoreCaseIgnoreWhiteSpace = 7, +} diff --git a/Code/Light.GuardClauses/Types.cs b/Code/Light.GuardClauses/Types.cs index 410c463..f340a05 100644 --- a/Code/Light.GuardClauses/Types.cs +++ b/Code/Light.GuardClauses/Types.cs @@ -11,4 +11,4 @@ public abstract class Types /// Gets the type. /// public static readonly Type FlagsAttributeType = typeof(FlagsAttribute); -} \ No newline at end of file +}