Validate parameters in async method

out parameter in async method c#
split this method into two one handling parameters check and the other handling asynchronous code
c# asynchronous programming model
async methods cannot have ref in or out parameters
await async c#
c# wait for async method to complete
c# async await explained
c# async method blocking

I'm writing a class which have synchronous and asynchronous versions of the same method void MyMethod(object argument) and Task MyMethodAsync(object argument). In sync version I validate argument with the simple check

if (argument == null)
    throw new ArgumentNullException("argument");

How should the same check look like in async method?

1) Same as for sync method

2) (Updated after first answer)

if (argument == null)
    return new Task.Factory.StartNew(() => { throw new ArgumentNullException("argument"); });

That depends a bit on when you want the error to be raised - i.e. eagerly, or as part of the awaitable. As with iterator blocks, if you want eager error checks, you need two methods, for example:

public Task<int> SomeMethod(..args..) {
    if(..args fail..) throw new InvalidOperationException(...);
    return SomeMethodImpl(...args...);
}
private async Task<int> SomeMethodImpl(...args...)
{
    ... await etc ...
}

This will then perform any argument checking as part of the initial call, not the awaitable. If you want the exception to be part of the awaitable, you can just throw it:

public async Task<int> SomeMethod(..args..) {
    if(..args fail..) throw new InvalidOperationException(...);
    ... await etc ...
}

However, in your example, the fact that you are returning a Task suggests that this is not actually an async method, but is an async (but not async) method. You can't just do:

return new Task(() => { throw new ArgumentNullException("argument"); });

because that Task will never have been started - and never will be. I suspect you would need to do something like:

try {
    throw new InvalidArgumentException(...); // need to throw to get stacktrace
} catch(Exception ex) {
    var source = new TaskCompletionSource<int>();
    source.SetException(ex);
    return source.Task;
}

which is... a bit of a mouthful and could probably be encapsulated a bit better. This will return a Task that indicates it is in the Faulted state.

C#: Parameter validation in "async"/"await" methods should be , Parameter validation in "async"/"await" methods should be wrapped. Code Smell. Major  This instance allows a function to access data route parameters, query string values and methods that allow you to return HTTP responses. Once defined, the route parameters are available to the function by calling the route_params method.


As per sonar rule S4457

Because of the way async/await methods are rewritten by the compiler, any exceptions thrown during the parameters check will happen only when the task is observed. That could happen far away from the source of the buggy code or never happen for fire-and-forget tasks.

Therefore it is recommended to split the method into two: an outer method handling the parameter checks (without being async/await) and an inner method to handle the iterator block with the async/await pattern.

This rule raises an issue when an async method throws any exception derived from ArgumentException and contains await keyword.

Noncompliant Code Example
public static async Task SkipLinesAsync(this TextReader reader, int linesToSkip) // Noncompliant
{
    if (reader == null) { throw new ArgumentNullException(nameof(reader)); }
    if (linesToSkip < 0) { throw new ArgumentOutOfRangeException(nameof(linesToSkip)); }

    for (var i = 0; i < linesToSkip; ++i)
    {
        var line = await reader.ReadLineAsync().ConfigureAwait(false);
        if (line == null) { break; }
    }
}

Compliant Solution
public static Task SkipLinesAsync(this TextReader reader, int linesToSkip)
{
    if (reader == null) { throw new ArgumentNullException(nameof(reader)); }
    if (linesToSkip < 0) { throw new ArgumentOutOfRangeException(nameof(linesToSkip)); }

    return reader.SkipLinesInternalAsync(linesToSkip);
}

private static async Task SkipLinesInternalAsync(this TextReader reader, int linesToSkip)
{
    for (var i = 0; i < linesToSkip; ++i)
    {
        var line = await reader.ReadLineAsync().ConfigureAwait(false);
        if (line == null) { break; }
    }
}

C# async-await: Parameter validation in "async"/"await" methods , Parameter validation in "async"/"await" methods should be wrapped. Code Smell. Major  Therefore it is recommended to split the method into two: an outer method handling the parameter checks (without being async/await) and an inner method to handle the iterator block with the async/await pattern. This rule raises an issue when an async method throws any exception derived from ArgumentException and contains await keyword.


Starting from C# 7.0, you can use use local function to reduce noise in code but still be compliant with argument check practice from sonar rule S4457. For example, this code will throw an ArgumentNullException in both cases: if you call it with await or without.

private Task WaitSeconds(int? durationInSeconds)
{
    if(durationInSeconds == null) throw new ArgumentNullException(nameof(durationInSeconds));
    async Task WaitSecondsInternal()
    {
        await Task.Delay(TimeSpan.FromSeconds(durationInSeconds.Value));
    }
    return WaitSecondsInternal();
}

A word of caution on argument validation in Async methods , I have been noticing around in some blogposts and code snippets a pattern being used when validating arguments in Task-returning async  When I iterate through a list of Object (Form) which are Future, the parameter formFile is not passing to the function. When I put a breakpoint on insertRequest line, I can't find formFile var but


Simply throw it like you did in the sync method, the TPL has various mechanisms in place to re-throw exception, for example when you read the .Result property or the access .Exception property.

Async, Exceptions and Library Design, This synchronous method then calls an internal async method that does method that performs the parameter validation and state validation. Override lifecycle methods to perform additional operations on components during component initialization and rendering. Lifecycle methods Before parameters are set. SetParametersAsync sets parameters supplied by the component's parent in the render tree: public override async Task SetParametersAsync(ParameterView parameters) { await


Async-Async: Consequences for exceptions, try { Task task1 = DoSomethingAsync(arg1); Task task2 It might do parameter validation before creating the IAsyncOperation , or it might  During field validation, the DataAnnotationsValidator component associates all reported validation results with the field. Model validation is performed when the user submits the form. During model validation, the DataAnnotationsValidator component attempts to determine the field based on the member name that the validation result reports.


An Overview of Async Method Return Types in C#, As you work with async/await in C#, you'll probably encounter some There are a few valid reasons for returning void from an async method, but the That being the case, you can't return data using ref or out parameters. Must return an asynchronous iterator from its __aiter__() method. Introduced by PEP 492. asynchronous iterator. An object that implements the __aiter__() and __anext__() methods. __anext__ must return an awaitable object. async for resolves the awaitables returned by an asynchronous iterator’s __anext__() method until it raises a


Control flow redux: exceptions in asynchronous code, What happens when an async method throws an exception? have a bit of a usability problem when it comes to argument validation: because  We chose to implement async methods in a similar way to iterator methods -- i.e. through the compiler transforming the method into a state-machine-object. The CLR has no safe way to store the address of an "out parameter" or "reference parameter" as a field of an object.