Skip to content

Commit

Permalink
Added more async helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
sakno committed Sep 25, 2024
1 parent 9ab5679 commit d7b396b
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/DotNext.Tests/DelegateHelpersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,28 @@ public static void ToAsync2()
func = new Action<int>(static _ => throw new Exception()).ToAsync();
True(func.Invoke(42, new(canceled: false)).IsFaulted);
}

[Fact]
public static void ToAsync3()
{
var func = new Action<int, int>(static (_, _) => { }).ToAsync();
True(func.Invoke(42, 42, new(canceled: false)).IsCompletedSuccessfully);
True(func.Invoke(42, 42, new(canceled: true)).IsCanceled);

func = new Action<int, int>(static (_, _) => throw new Exception()).ToAsync();
True(func.Invoke(42, 42, new(canceled: false)).IsFaulted);
}

[Fact]
public static async Task ToAsync4()
{
var func = new Func<int, int, int>(static (x, y) => x + y).ToAsync();
Equal(84, await func.Invoke(42, 42, new(canceled: false)));
True(func.Invoke(42, 42, new(canceled: true)).IsCanceled);

func = new Func<int, int, int>(static (_, _) => throw new Exception()).ToAsync();
await ThrowsAsync<Exception>(func.Invoke(42, 42, new(canceled: false)).AsTask);
}

[Fact]
public static void HideReturnValue1()
Expand Down
76 changes: 76 additions & 0 deletions src/DotNext/DelegateHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,82 @@ private static ValueTask Invoke(this Action action, CancellationToken token)
return task;
}

/// <summary>
/// Converts action to async delegate.
/// </summary>
/// <typeparam name="T1">The type of the first argument to be passed to the action.</typeparam>
/// <typeparam name="T2">The type of the second argument to be passed to the action.</typeparam>
/// <param name="action">Synchronous action.</param>
/// <returns>The asynchronous function that wraps <paramref name="action"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="action"/> is <see langword="null"/>.</exception>
public static Func<T1, T2, CancellationToken, ValueTask> ToAsync<T1, T2>(this Action<T1, T2> action)
{
ArgumentNullException.ThrowIfNull(action);

return action.Invoke;
}

private static ValueTask Invoke<T1, T2>(this Action<T1, T2> action, T1 arg1, T2 arg2, CancellationToken token)
{
ValueTask task;
if (token.IsCancellationRequested)
{
task = ValueTask.FromCanceled(token);
}
else
{
task = ValueTask.CompletedTask;
try
{
action.Invoke(arg1, arg2);
}
catch (Exception e)
{
task = ValueTask.FromException(e);
}
}

return task;
}

/// <summary>
/// Converts function to async delegate.
/// </summary>
/// <typeparam name="T1">The type of the first argument to be passed to the action.</typeparam>
/// <typeparam name="T2">The type of the second argument to be passed to the action.</typeparam>
/// <typeparam name="TResult">The type of the return value.</typeparam>
/// <param name="func">Synchronous action.</param>
/// <returns>The asynchronous function that wraps <paramref name="func"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="func"/> is <see langword="null"/>.</exception>
public static Func<T1, T2, CancellationToken, ValueTask<TResult>> ToAsync<T1, T2, TResult>(this Func<T1, T2, TResult> func)
{
ArgumentNullException.ThrowIfNull(func);

return func.Invoke;
}

private static ValueTask<TResult> Invoke<T1, T2, TResult>(this Func<T1, T2, TResult> func, T1 arg1, T2 arg2, CancellationToken token)
{
ValueTask<TResult> task;
if (token.IsCancellationRequested)
{
task = ValueTask.FromCanceled<TResult>(token);
}
else
{
try
{
task = new(func.Invoke(arg1, arg2));
}
catch (Exception e)
{
task = ValueTask.FromException<TResult>(e);
}
}

return task;
}

/// <summary>
/// Creates a delegate that hides the return value.
/// </summary>
Expand Down

0 comments on commit d7b396b

Please sign in to comment.