Roslyn: ?. operator and await question (potential bug)

Created on 11 Jun 2019  路  5Comments  路  Source: dotnet/roslyn

Hi Guys!

Have a look at following sample:

using System;
using System.Threading.Tasks;

namespace ConsoleApp15
{
    public class Foo
    {
        public void Bar() { }
        public async Task Bar2() { await Task.Delay(0);  return; }
    }
    class Program
    {
        static async Task Main(string[] args)
        {
            Foo foo = null;
            foo?.Bar(); // Not throws
            await foo?.Bar2(); // Throws

            Console.WriteLine("Hello World!");
        }
    }
}

Here when I call Bar I use ?. operator and expect method to not be called and it is not called and no exception thrown. Right on the next line I expect exactly the same behaviour but I do get NullReferenceException. Is that something expected? (If it is then I would say it looks very inconsistent)

VS 2019 16.1.1
C# Latest Minor

Thank you

Most helpful comment

All 5 comments

Think of the offending line as being interpreted as something like Task.Await(foo?.Bar2());. Then you can see that you are indeed awaiting null. There are proposals, I believe, to add something like await? to cover this annoyance.

Think of the offending line as being interpreted as something like Task.Await(foo?.Bar2());. Then you can see that you are indeed awaiting null. There are proposals, I believe, to add something like await? to cover this annoyance.

That is correct and clear but still very inconsistent with code without await. I would personally prefer to not have await? and change current behaviour, otherwise we add one more inconsistenly on top of existing inconsistency. Like imagine you had code await? foo.Bar() and then for some reason function become sync and await has gone. Then we can't simply delete await? and have to change code from await? foo.Bar() to foo?.Bar().

Does not look good IMHO

imagine you had code await? foo.Bar() and then for some reason function become sync and await has gone. Then we can't simply delete await? and have to change code from await? foo.Bar() to foo?.Bar().

You would still need to write await? foo?.Bar() which would be self-consistent with or without the await.

imagine you had code await? foo.Bar() and then for some reason function become sync and await has gone. Then we can't simply delete await? and have to change code from await? foo.Bar() to foo?.Bar().

You would still need to write await? foo?.Bar() which would be self-consistent with or without the await.

Ah, now Is clear. is that something already discussed and agreed? Just interesting if this might go to any version soon?

Was this page helpful?
0 / 5 - 0 ratings