Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tell the caller that a `async Task<T>` method may return null

My situation is similar to the one described Proper nullable annotation for async generic method that may return default(T).

However, I'd like to know the proper way to let the caller know that the "return value" might be null.

    public async Task<T> GetAsync<T>()
    {
        // sometimes returns default(T)!;
    }

If this was not an async method I could use the MaybeNull attribute.

    [return: MaybeNull]
    public T Get<T>()
    {
        // sometimes returns default(T)!;
    }

If it was not generic I could just use the ? syntax.

    public async Task<string?> GetAsync()
    {
        // sometimes returns default(string)!;
    }

Is there a way to let the caller know that it could be null without adding a generic constraint?

EDIT: To clarify I mean let the compiler know that the value in the task may be null. I suppose the reverse is also true. I'm mostly interested in how this is supposed to work with the new C# nullable reference syntax.

I can do something like this just fine

    var a = await GetAsync<string?>(); // a is null
    var b = await GetAsync<int?>(); // b is null
    var c = await GetAsync<string>(); // c is null.  Wait string is not supposed to be null and the compiler won't warn you if you use it!
    var d = await GetAsync<int>(); // d is 0

EDIT: I can do something like this just fine

    var a = await Get<string?>(); // a is null
    var b = await Get<int?>(); // b is null
    var c = await Get<string>(); // c is null.  
    var d = await Get<int>(); // d is 0

The suggestion of Nullable reference types: How to specify "T?" type without constraining to class or struct is similar, but the Box class can be modified to provide the proper warnings where I cannot change the implementation of Task.

like image 327
drs9222 Avatar asked Jun 12 '20 14:06

drs9222


People also ask

Can async method return null?

in an async function that returns a Task or Task<T> , you simply return or return a value, and the result of the function is implicitly converted to a task, so there is no danger of returning null .

How do I return a NULL from a task?

Returning null from a non-async Task-returning method One way to prevent this NRE while still returning null is to check that the result of the method is not null and await a valid Task if it is. We can do this with the null-coalescing operator; for example: result = await (NonAsyncFoo() ?? Task.

Is an async method that returns task?

Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.

What happens when you call an async method?

The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete. In most cases, that behavior isn't expected.


1 Answers

In C# 8, you can't express this because you can't apply the [MaybeNull] attribute to the type argument to Task<T>.

In C# 9, you can just make the return type nullable.

public async Task<T?> GetAsync<T>()
{
    // sometimes returns default(T)!;
}
like image 176
Rikki Gibson Avatar answered Nov 01 '22 10:11

Rikki Gibson