Click here to Skip to main content
15,891,649 members
Articles / All Topics

Exceptional Edge Cases

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
16 Dec 2015CPOL2 min read 3.8K   1  
Exceptional edge cases

It’s stated as conventional wisdom that in .NET, a throw expression must throw an object of a type that is System.Exception, or derived from System.Exception. Here’s the language from the C# specification (Section 8.9.5):

A throw statement with an expression throws the value produced by evaluating the expression. The expression must denote a value of the class type System.Exception, of a class type that derives from System.Exception, or of a type parameter type that has System.Exception (or a subclass thereof) as its effective base class.

Let’s play with the edge cases. What will this do:

C#
throw default(NotImplementedException);

The expression is typed correctly (it is a NotImplementedException). But, it’s null. The answer to this is in the next sentence of the C# Specification:

If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

That means this is also legal:

C#
throw null;

It will throw a NullReferenceException, as specified above.

Now, let’s see what happens if we work with a type that can be converted to an exception:

C#
struct Exceptional
{     
   public static implicit operator Exception(Exceptional e)     
   {
         return null;     
   }
}

An Exceptional can be converted (implicitly) to an Exception. But this results in a compile time error:

C#
throw new Exceptional();

The compiler reports that the type thrown must be derived from System.Exception. So, let’s rewrite the code so that it is:

C#
Exception e = new Exceptional();
throw e;

The first line creates an Exceptional struct. Assigning it to a variable of type Exception invokes the implicit conversion. Now, it is of type Exception, and can be thrown.

Finally, what about this expression:

C#
dynamic d = new Exceptional();
throw d;

In most places in the language, where an expression must evaluate to a specific type, an expression of type dynamic is allowed.

Here, we have the joy of edge cases. The spec (as I’ve quoted above) doesn’t speak to this case. Where the spec is silent, sometimes developers interpret them differently. The classic compiler (pre-Roslyn) accepts throwing an expression that is dynamic. The Roslyn (VS 2015) compiler does not. I expect this may change, and the spec may get updated to explicitly state the behavior.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Bill Wagner Software LLC
United States United States
Bill Wagner is one of the world's foremost C# developers and a member of the ECMA C# Standards Committee. He is President of the Humanitarian Toolbox, has been awarded Microsoft Regional Director and .NET MVP for 10+years, and was recently appointed to the .NET Foundation Advisory Council. Wagner currently works with companies ranging from start-ups to enterprises improving the software development process and growing their software development teams.

Comments and Discussions

 
-- There are no messages in this forum --