Taking something that can't be done, and then doing it.

by Jiří {x2} Činčura

Two interesting edge cases for C#6's when clause

Published 3 Dec 2015 in .NET and C#

Last weekend I was speaking on a conference and one of my two sessions was about new features in C# 6. I like when people ask questions about topic I’m explaining and in this session there were two questions I’d like to share with you, because I think these are very interesting (and also I’m pretty sure it’s described to a detail in the specification, but that’s boring 8-)) and hence worth sharing.

The feature

C# 6 brings a new feature for optional filter for catch clause. Instead of just having a type the catch block handles you can also add a when clause and some condition. Here’s a little example.

1
2
3
4
5
6
7
8
try
{
	// something...
}
catch (SomeException ex) when (ex.Something == something)
{
	// handle it...
}

Pretty straightforward, right?

Can you use await in when clause?

Just pause here for a minute and think about it. Isn’t that an awesome idea? Maybe bit crazy. Anyway, let’s try it out.

1
2
3
4
5
6
7
8
try
{
	// something...
}
catch (SomeException ex) when (await Whoa(ex))
{
	// handle it...
}

Where the Whoa might look like this.

1
2
3
4
static Task<bool> Whoa(Exception ex)
{
	return Task.FromResult(true);
}

Well this results in nice CS7094 with pretty clear message Cannot await in the filter expression of a catch clause.

Alright, so you cannot use await in when clause.

What if the code in when clause throws an exception?

That seems to be valid question. And thinking about it there might be two cases. First case when the code throws exception that’s of type the catch clause could handle and the other when the exception is of “incompatible” type. Let’s try the first one as that might provide more fun.

1
2
3
4
5
6
7
8
try
{
	throw new ArgumentException();
}
catch (ArgumentException ex) when (Throw<ArgumentNullException>(ex))
{
	Console.WriteLine($"Handling {ex.GetType().Name}");
}

And the helper Throw method.

1
2
3
4
static bool Throw<TException>(Exception ex) where TException : Exception, new()
{
	throw new TException();
}

Running this code will clearly show the exception is not handled. Whether the type is “compatible” with the catch clause or not doesn’t matter (one might quickly try it changing the when clause to i.e. when (Throw<InvalidCastException>(ex))).

Alright, so throwing exception is basically the same as returning false.

Closing

I was kind of expecting it to behave like this and it seems to be reasonable behavior to expect as well.

I like poking into (any) language or system from different angles and discover how it behaves and what was the reasoning behind that behavior.