Why do I get an exception when passing "null" constant but not when passing a "null" string reference?

Solution 1:

Just decompile the code to work out what's going on.

string.Format("{0}", null)

calls the most specific applicable overload, which is string.Format(string, object[]).

The overloads of string.Format are:

Format(String, Object)
Format(String, Object[])
Format(IFormatProvider, String, Object[])
Format(String, Object, Object)
Format(String, Object, Object, Object)

Hopefully it's obvious why the last three options are invalid.

To work out which of the first two to use, the compiler compares the conversion from null to Object to the conversion from null to Object[]. The conversion to Object[] is deemed "better" because there's a conversion from Object[] to Object, but not vice versa. This is the same logic by which if we had:

Foo(String)
Foo(Object)

and called Foo(null), it would pick Foo(String).

So your original code is equivalent to:

object[] values = null;
string.Format("{0}", values);

At this point, hopefully you'd expect an ArgumentNullException - as per the documentation.