Throwing things in C#

One of the fun parts of exploring and investigating the C# Language Specification is writing code that you would not write for a production application. It’s fun to write code that bends the language features.

Most developers are familiar with the concept that in .NET, exceptions are always objects that are derived from System.Exception.

This is covered in S. 8.9.5 of the C# Language Specification (4th edition). It states:

“The expression [in a throw statement] must denote a value of the class type System.Exception, of a class type that derives from System.Exception (or a subclass thereof), or of a type parameter type that has System.Exception (or a subclass thereof) as its effective base class.”

Here are examples of throwing an object derived from System.Exception, and a type parameter that has System.Exception as its base class:

 

public static void ThrowThingsVersionOne()
{     throw new InvalidOperationException
        ("Because the object's state is investigating exceptions");
}
 
public static void ThrowThingsVersionTwo<T>()      where T : System.Exception, new()
{     throw new T();
}

 

This section goes on to explain what happens in this instance:

 

public static void ThrowThingsVersionThree()
{     throw null;
}

 

The spec states (also in S. 8.9.5):

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

You could write this:

 

public static void ThrowThingsVersionFour()
{     throw default(NullReferenceException);
}

 

Or, if wanted to confuse the developers that read your code later, you could write this:

 

public static void ThrowThingsVersionFive()
{     // Throws a NullReferenceException:
    throw default(InvalidOperationException);
}

 

Now, we are starting to get to some harder to read code. I’ve added an explanatory comment. Without it, we’re beginning to write code that can confuse other developers. Let’s see how far we can take this.

Let’s try this:

 

public static void ThrowThingsVersionSix()
{     throw default(string);
}

 

The compiler prevents this sort of evil. I’ve tried to throw null, but I’ve declared it such that the compile time type is System.String. That’s not derived from System.Exception, so the compiler flags the error.

Well, let’s learn how good the compiler is at determining what’s being thrown. First, let’s try an implicitly typed local variable:

 

public static void ThrowThingsVersionSeven()
{     var e = new InvalidOperationException
        ("Because the object's state is investigating exceptions");     throw e;
}

 

That compiles, and throws the expected InvalidOperationException. Implicitly typed variables have a compile time type that matches the right hand side of the assignment. How about this:

 

public static void ThrowThingsVersionEight()
{     object e = new InvalidOperationException
        ("Because the object's state is investigating exceptions");     throw e;
}

 

It doesn’t compile, because the compile time type of ‘e’ is System.Object. Well, let’s try to coerce the compiler and bend it to our evil will:

 

public static void ThrowThingsVersionNine()
{     dynamic e = new InvalidOperationException
        ("Because the object's state is investigating exceptions");     throw e;
}

 

The compiler still thwarts our evil intent. This doesn’t compile, because ‘dynamic’ doesn’t derive from System.Exception. Because the language rules for dynamic allow us to try to convert it to any type, we can bend the compiler to our evil will:

 

public static void ThrowThingsVersionTen()
{     dynamic e = new InvalidOperationException
        ("Because the object's state is investigating exceptions");     throw (System.Exception)e;
}

 

Bwa ha ha ha, I say. We’ve finally found a path to force the compiler to pure evil.

 

To finish, let’s try to throw something that’s not an exception. Without running the code, try and figure out what this might do:

 

public static void ThrowThingsVersionEleven()
{     dynamic e = "Because the object's state is investigating exceptions";     throw (System.Exception)e;
}

 

I’ll update this post toward the end of the week with the explanation.

Tags: C#
Created: 2/23/2016 4:15:30 PM

Current Projects

I create content for .NET Core. My work appears in the .NET Core documentation site. I'm primarily responsible for the section that will help you learn C#.

All of these projects are Open Source (using the Creative Commons license for content, and the MIT license for code). If you would like to contribute, visit our GitHub Repository. Or, if you have questions, comments, or ideas for improvement, please create an issue for us.

I'm also the president of Humanitarian Toolbox. We build Open Source software that supports Humanitarian Disaster Relief efforts. We'd appreciate any help you can give to our projects. Look at our GitHub home page to see a list of our current projects. See what interests you, and dive in.

Or, if you have a group of volunteers, talk to us about hosting a codeathon event.