Skip to content

Commit

Permalink
Merge pull request #155 from AArnott/net9Params
Browse files Browse the repository at this point in the history
Add alloc-free `params ReadOnlySpan<object?>` overloads to .NET 9
  • Loading branch information
AArnott authored Dec 20, 2024
2 parents b6e9f7f + 26dfdbe commit bd6858d
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 2 deletions.
33 changes: 33 additions & 0 deletions src/Validation/Assumes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@ public static void False([DoesNotReturnIf(true)] bool condition, [Localizable(fa
}
}

#if NET9_0_OR_GREATER
/// <inheritdoc cref="False(bool, string, object?[])"/>
[DebuggerStepThrough]
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public static void False([DoesNotReturnIf(true)] bool condition, [Localizable(false)] string unformattedMessage, params ReadOnlySpan<object?> args)
{
if (condition)
{
Fail(Format(unformattedMessage, args));
}
}

#endif

/// <summary>
/// Throws an public exception if a condition evaluates to false.
/// </summary>
Expand Down Expand Up @@ -189,6 +203,21 @@ public static void True([DoesNotReturnIf(false)] bool condition, [Localizable(fa
}
}

#if NET9_0_OR_GREATER

/// <inheritdoc cref="True(bool, string, object?[])"/>
[DebuggerStepThrough]
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public static void True([DoesNotReturnIf(false)] bool condition, [Localizable(false)] string unformattedMessage, params ReadOnlySpan<object?> args)
{
if (!condition)
{
Fail(Format(unformattedMessage, args));
}
}

#endif

/// <summary>
/// Unconditionally throws an <see cref="InternalErrorException"/>.
/// </summary>
Expand Down Expand Up @@ -324,7 +353,11 @@ public static Exception Fail([Localizable(false)] string? message, Exception? in
/// <summary>
/// Helper method that formats string arguments.
/// </summary>
#if NET9_0_OR_GREATER
private static string Format(string format, params ReadOnlySpan<object?> arguments)
#else
private static string Format(string format, params object?[] arguments)
#endif
{
return PrivateErrorHelpers.Format(format, arguments);
}
Expand Down
7 changes: 7 additions & 0 deletions src/Validation/PrivateErrorHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,16 @@ internal static Type TrimGenericWrapper(Type type, Type? wrapper)
/// Helper method that formats string arguments.
/// </summary>
/// <returns>The formatted string.</returns>
#if NET9_0_OR_GREATER
internal static string Format(string format, params ReadOnlySpan<object?> arguments)
{
return string.Format(CultureInfo.CurrentCulture, format, arguments);
}
#else
internal static string Format(string format, params object?[] arguments)
{
return string.Format(CultureInfo.CurrentCulture, format, arguments);
}
#endif
}
}
82 changes: 82 additions & 0 deletions src/Validation/Requires.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,18 @@ public static void Argument([DoesNotReturnIf(false)] bool condition, string? par
}
}

#if NET9_0_OR_GREATER
/// <inheritdoc cref="Argument(bool, string?, string, object?[])"/>"
[DebuggerStepThrough]
public static void Argument([DoesNotReturnIf(false)] bool condition, string? parameterName, string message, params ReadOnlySpan<object?> args)
{
if (!condition)
{
throw new ArgumentException(Format(message, args), parameterName);
}
}
#endif

/// <summary>
/// Throws an <see cref="ArgumentException"/> if a condition does not evaluate to true.
/// </summary>
Expand Down Expand Up @@ -440,6 +452,19 @@ public static void Argument([DoesNotReturnIf(false)] bool condition, string? par
}
}

#if NET9_0_OR_GREATER
/// <inheritdoc cref="Argument(bool, string?, ResourceManager, string, object?[])"/>
[DebuggerStepThrough]
public static void Argument([DoesNotReturnIf(false)] bool condition, string? parameterName, ResourceManager resourceManager, string unformattedMessageResourceName, params ReadOnlySpan<object?> args)
{
NotNull(resourceManager, nameof(resourceManager));
if (!condition)
{
throw new ArgumentException(Format(resourceManager, unformattedMessageResourceName, args), parameterName);
}
}
#endif

/// <summary>
/// Throws an ArgumentException.
/// </summary>
Expand All @@ -462,6 +487,16 @@ public static Exception Fail(string unformattedMessage, params object?[] args)
throw Fail(Format(unformattedMessage, args));
}

#if NET9_0_OR_GREATER
/// <inheritdoc cref="Fail(string, object?[])"/>
[DebuggerStepThrough]
[DoesNotReturn]
public static Exception Fail(string unformattedMessage, params ReadOnlySpan<object?> args)
{
throw Fail(Format(unformattedMessage, args));
}
#endif

/// <summary>
/// Throws an ArgumentException.
/// </summary>
Expand All @@ -473,6 +508,16 @@ public static Exception Fail(Exception? innerException, string unformattedMessag
throw new ArgumentException(Format(unformattedMessage, args), innerException);
}

#if NET9_0_OR_GREATER
/// <inheritdoc cref="Fail(Exception, string, object?[])"/>
[DebuggerStepThrough]
[DoesNotReturn]
public static Exception Fail(Exception? innerException, string unformattedMessage, params ReadOnlySpan<object?> args)
{
throw new ArgumentException(Format(unformattedMessage, args), innerException);
}
#endif

#if !NET35
/// <summary>
/// Throws an <see cref="InvalidEnumArgumentException"/> if a given value is not a named value of the enum type.
Expand Down Expand Up @@ -609,6 +654,35 @@ public static void ValidElements<T>([ValidatedNotNull] IEnumerable<T> values, Pr
}
}

#if NET9_0_OR_GREATER
/// <inheritdoc cref="ValidElements{T}(IEnumerable{T}, Predicate{T}, string?, string, object?[])"/>
[DebuggerStepThrough]
public static void ValidElements<T>([ValidatedNotNull] IEnumerable<T> values, Predicate<T> predicate, string? parameterName, string unformattedMessage, params ReadOnlySpan<object?> args)
{
// To whoever is doing random code cleaning:
// Consider the performance when changing the code to delegate to NotNull.
// In general do not chain call to another function, check first and return as early as possible.
if (values is null)
{
throw new ArgumentNullException(nameof(values));
}

if (predicate is null)
{
throw new ArgumentNullException(nameof(predicate));
}

foreach (T value in values)
{
if (!predicate(value))
{
throw new ArgumentException(PrivateErrorHelpers.Format(unformattedMessage, args), parameterName);
}
}
}

#endif

/// <summary>
/// Validates some expression describing the acceptable condition for an argument evaluates to true.
/// </summary>
Expand All @@ -627,12 +701,20 @@ public static void ValidState(bool condition, string message)
/// <summary>
/// Helper method that formats string arguments.
/// </summary>
#if NET9_0_OR_GREATER
private static string Format(string format, params ReadOnlySpan<object?> arguments)
#else
private static string Format(string format, params object?[] arguments)
#endif
{
return PrivateErrorHelpers.Format(format, arguments);
}

#if NET9_0_OR_GREATER
private static string Format(ResourceManager resourceManager, string resourceName, params ReadOnlySpan<object?> arguments)
#else
private static string Format(ResourceManager resourceManager, string resourceName, params object?[] arguments)
#endif
{
return Format(resourceManager.GetString(resourceName, CultureInfo.CurrentCulture) ?? $"Missing resource named {resourceManager}", arguments);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Validation/Validation.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0;netstandard2.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0;netstandard2.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net462</TargetFrameworks>
<TargetFrameworks Condition="'$(MSBuildRuntimeType)'=='Full'">$(TargetFrameworks);net35</TargetFrameworks>
<Title>Input and runtime validation</Title>
Expand Down
26 changes: 26 additions & 0 deletions src/Validation/Verify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ public static void Operation([DoesNotReturnIf(false)] bool condition, string unf
}
}

#if NET9_0_OR_GREATER

/// <inheritdoc cref="Operation(bool, string, object?[])"/>
[DebuggerStepThrough]
public static void Operation([DoesNotReturnIf(false)] bool condition, string unformattedMessage, params ReadOnlySpan<object?> args)
{
if (!condition)
{
throw new InvalidOperationException(PrivateErrorHelpers.Format(unformattedMessage, args));
}
}

#endif

/// <summary>
/// Throws an <see cref="InvalidOperationException"/> if a condition is false.
/// </summary>
Expand Down Expand Up @@ -92,6 +106,18 @@ public static Exception FailOperation(string message, params object?[] args)
throw new InvalidOperationException(PrivateErrorHelpers.Format(message, args));
}

#if NET9_0_OR_GREATER

/// <inheritdoc cref="FailOperation(string, object?[])"/>
[DebuggerStepThrough]
[DoesNotReturn]
public static Exception FailOperation(string message, params ReadOnlySpan<object?> args)
{
throw new InvalidOperationException(PrivateErrorHelpers.Format(message, args));
}

#endif

/// <summary>
/// Throws an <see cref="ObjectDisposedException"/> if an object is disposed.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion test/Validation.Tests/Validation.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
<TargetFrameworks Condition="'$(OS)' == 'Windows_NT'">$(TargetFrameworks);net472</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
Expand Down

0 comments on commit bd6858d

Please sign in to comment.