0

Why does this program compile?

class Program
{
    static void Main(string[] args)
    {
        throw null;
    }
}

From 8.9.5 of the C# Language Specification,

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. If evaluation of the expression produces null, a System.NullReferenceException is thrown instead.

Obviously, null evaluates to null, so the last sentence is where this behavior is from, but how does it even get there? Attempting to throw other values that do not derive from System.Exception results in a compiler error, error CS0155: The type caught or thrown must be derived from System.Exception.


The top answer on the proposed duplicate begins with (emphasis mine):

Because the language specification expects an expression of type System.Exception there (therefore, null is a valid in that context) ...

The expression null is System.Exception evaluates to false, and produces a compiler warning warning CS0184: The given expression is never of the provided ('Exception') type, so I'm comfortable making the assertion that null isn't valid where a System.Exception is required.

Community
  • 1
  • 1
jdphenix
  • 15,022
  • 3
  • 41
  • 74
  • Because other values are *typed*. Null is not typed. Perhaps you could argue that you should have to write `throw (Exception)null;` - however, since you can pass `null` without explicitly specifying the type as an argument to `DoSomething(Exception ex)` - you should also be able to pass 'null' as an argument to `throw` – Rob Nov 25 '16 at 01:42
  • @Rob, Consider a method `static Type GetType(T t) { return typeof (T); }`. You can pass it a null reference that is typed, i.e. `GetType((Exception)null)` and it performs like you'd expect. If you try to directly pass `null`, type inference can't determine the type being passed. Why doesn't the same kind of problem happen with `throw null`? – jdphenix Nov 25 '16 at 01:48
  • @jdphenix Well, that's specific to generics in C#. Since `null` is not typed, you need to provide a type that `T` can bind to. In the proposed duplicate (I'm not convinced it's a duplicate yet), it mentions that the check doesn't accomplish much, as you could still pass null indirectly (if a method were simply returning `null`). So explicitly preventing `throw null` doesn't seem to have any benefit in itself – Rob Nov 25 '16 at 01:49
  • @jdphenix to answer your edit, the proposed duplicate also quotes the ECMA spec which states: `System.NullReferenceException is thrown if obj is null.` – Steve Nov 25 '16 at 02:13
  • CIL allows objects of any type to be thrown, C# does not. The referenced ECMA specification addresses the former. – jdphenix Nov 25 '16 at 02:16

0 Answers0