15

I have the following code:

await _user?.DisposeAsync();

Visual Studio highlights this code, saying 'Possible NullReferenceException'

by the way, without await Visual Studio doesn't show this warning Why NullReferenceException is possible here?

Maxim Kitsenko
  • 2,042
  • 1
  • 20
  • 43

3 Answers3

16

await null will throw a NullReferenceException. Therefore if _user is null, then _user?.DisposeAsync() will return null, and the await will throw.

You can do:

if (_user != null)
{
    await _user.DisposeAsync();
}

(you might need a local copy of _user if it might change between reads)

or:

await (_user?.DisposeAsync() ?? ValueTask.CompletedTask);

(Prior to .NET 5, you will need:)

await (_user?.DisposeAsync().AsTask() ?? Task.CompletedTask);
canton7
  • 37,633
  • 3
  • 64
  • 77
  • Didn't figure out the .AsTask() extension, but this works: `await (_user?.DisposeAsync() ?? Task.CompletedTask);` – jornhd Mar 30 '22 at 11:46
  • @jornhd [`DisposeAsync` returns a `ValueTask`](https://learn.microsoft.com/en-us/dotnet/api/system.iasyncdisposable.disposeasync?view=net-6.0). You can't apply `??` between a `ValueTask?` and a `Task`, [see here](https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMBWAbjz1QA4SA2IgMQHtWAKASQEEBnAJ5QAxgBEAlnwAOrPgEMARgBsApkWAALcVADmASjwBvPEVOnUATiIdN2nQH4AdBOmyV/IcI56i9+40cAYVYAWylVYBU4VAY9CiI8AF8gA=). It looks like your `DisposeAsync()` method returns a `Task` and not a `ValueTask`? So it doesn't come from `IAsyncDisposable` – canton7 Mar 30 '22 at 12:06
4

Async methods return a Task that can be awaited. If _user is null then you would not be returning a Task but null instead

Dan D
  • 2,493
  • 15
  • 23
2

await is expecting a result. If _user is null then the result will be null, hence the NullReferenceException.

Steve Todd
  • 1,250
  • 6
  • 13