tabs ↹ over ␣ ␣ ␣ spaces

by Jiří {x2} Činčura

Unexpected finding about “await using var”

8 Mar 2021 2 mins C#, Roslyn

I’m now updating my ConfigureAwaitChecker to handle await using and await foreach (release soon, if you’d like to ask) and when trying to handle await using var I was surprised how the compiler interprets that.

Let me first clear, that the same applies to using var, I’m just going to use await using var, because that’s what I’m actually working with.

Initial expectation

I always thought about the await using var as a shortcut. Shortcut in a sense that the pieces of code following are simply in { and } where the closing } would be at the of the method (or before other } from pieces of code above). And from a point of basic understanding how the code is going to behave that’s absolutely fine and correct. But when dealing with syntax trees, the story is different. Very different.

Regular block

public async Task M1() 
{
	await using (var _ = Foo())
	{ }
}

The code above is UsingStatementSyntax node and has an AwaitKeyword. So far so good.

Regular block

The “shortcut” block

public async Task M2() 
{
	await using var _ = Foo();
}

Yet this code is completely different story. This is a LocalDeclarationStatementSyntax, again with an AwaitKeyword and also with an UsingKeyword. Unexpected. Yes. At least it surprised me the first time. When you think about it obviously makes sense. It was just, …, unexpected.

The “shortcut” block

Closing

And now you know. But unless you deal with syntax trees, Roslyn and analyzers and/or code fixes, well, I don’t know if this has any value.

Related post.

Profile Picture Jiří Činčura is .NET, C# and Firebird expert. He focuses on data and business layers, language constructs, parallelism, databases and performance. For almost two decades he contributes to open-source, i.e. FirebirdClient. He works as a senior software engineer for Microsoft. Frequent speaker and blogger at www.tabsoverspaces.com.