61

The below code will throw Argument Null Exception

var test = string.Format("{0}", null); 

However, this will give back an empty string

string something  = null; 
var test = string.Format("{0}", something); 

Just curious to know why the second piece of code doesn't throw up exception. Is this a bug ?

2
  • 1
    Interesting question! Please remember to use code-block formatting in the future, it makes the question much more readable. I went ahead and fixed it for you. Commented Jul 1, 2014 at 17:38
  • Thank You for editing. when I am about to edit you did it by the time already :) Commented Jul 1, 2014 at 17:41

3 Answers 3

77

The difference is that the first piece of code is calling string.Format(string, object[])... whereas the second piece of code is calling string.Format(string, object).

null is a valid argument for the second method (it's just expected to be the value for the first placeholder), but not the first (where the null would usually be the array of placeholders). In particular, compare the documentation for when NullArgumentException is thrown:

string.Format(string, object):
format is null

But:

string.Format(string, object[]):
format or args is null

Think of string.Format(string, object) as being implemented something like:

public static string Format(string format, Object arg0)
{
    return string.Format(format, new object[] { arg0 } );
}

So after a bit of replacement, your code is closer to:

// Broken code
object[] args = null; // No array at all
var test = string.Format("{0}", args); 

// Working code
object[] args = new object[] { null }; // Array with 1 value
var test = string.Format("{0}", args); 
Sign up to request clarification or add additional context in comments.

11 Comments

+1. The last code block was what finally gave me the 'ah ha!' moment.
If someone still wonders about the rules that in this case make the compiler choose string.Format(string, params object[]) over string.Format(string, object) might want to read the C# specification chapter "Better function member" (in ECMA standard it is chapter 14.4.2.2, in current MS standard it is chapter 7.5.3.2) -- it boils down to that the null argument does not require params object[] to be expanded, and that object[] is a more specific parameter type than object.
@elgonzo: I don't know how well such a thing could be worked into the existing .NET now, but an amazing number of problems have resulted from the inability to "prioritize" overloads or control conversions should be associated with them. In some cases, the notion of "specificity" makes sense, but there are many others where it yields nonsensical results. I'm not sure one could devise better "rules", though--what's really needed is a means of letting the overloads themselves say (via attributes) what kinds of conversion should or should not be applied.
@supercat, you misunderstood something -- there is no conversion neccessary. You can assign a literal null value to an object array without any conversion (like object[] arr = null;), right? There is nothing nonsensical about it...
@elgonzo: In any case, I think my point is that while null literal is implicitly convertible to any reference type, I do not think it's helpful to consider it a "better" match for a SiameseCat than for an Animal. In some cases, a null literal may be legitimate argument for one overload, but not another; being able to let the overloads indicate which one should be preferable given a null literal would seem better than having the compiler choose the one which is, if anything, less likely to be prepared to accept it.
|
16

The second code snippet is calling the following overload:

Format(String, Object)

Here the value can be null, as per the documentation.

The first code snippet uses the following overload:

Format(String, Object[])  

Here the second value cannot be null, as per the documentation.

4 Comments

But, in the document it also tells "Thrown by all overloads". Am I missing something?
@AmitJoki, you missed the part "Condition: format is null." there in the documentation...
@AmitJoki It states which parameters being null results in it being thrown.
@elgonzo yeah! Got it.
0

A minor point not mentioned by existing answers, and almost makes the question moot:

The full message for the ArgumentNullException is:

Value cannot be null.
Parameter name: args

Also part of the issue here is null is of any type. Explicitly casting it to string or object (or use the C# default() feature) would avoid the problem.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.