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.
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 .
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.
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.
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.
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)!;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With