Click here to Skip to main content
15,895,799 members
Articles / Programming Languages / C#

Throwing Things in C#

Rate me:
Please Sign up or sign in to vote.
4.83/5 (4 votes)
24 Feb 2016CPOL2 min read 11.1K   2   4
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:

C#
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:

C#
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:

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

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

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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.

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

 
GeneralMy vote of 5 Pin
Gary Wheeler29-Feb-16 7:25
Gary Wheeler29-Feb-16 7:25 
QuestionThis is funny Pin
Michael Breeden26-Feb-16 1:22
Michael Breeden26-Feb-16 1:22 
Total nonsense, but totally cool nonsense.
...So does the compiler see "dynamic" or look ahead and see the caste?
I suppose I could test, but I might damage something....
I think VS would fail to see the caste... That's my guess and I'm sticking with it.

BugCode snippets Pin
Giacomo Pozzoni24-Feb-16 2:10
Giacomo Pozzoni24-Feb-16 2:10 
GeneralRe: Code snippets Pin
Bill Wagner24-Feb-16 2:45
professionalBill Wagner24-Feb-16 2:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.