views:

79

answers:

5

Consider string.Format() whose parameters are a string and, among others in the overload list, an object[] or many objects.

This statement succeeds:

string foo = string.Format("{0} {1}", 5, 6);

as does this:

object[] myObjs = new object[] {8,9};
string baz = string.Format("{0} and {1}", myObjs;

as does an array of strings:

string[] myStrings = new string[] {"abc", "xyz"};
string baz = string.Format("{0} {1}", myStrings);

It seems that the integers, when specified individually, can be boxed or coerced to type object, which in turn is coerced to a string.

This statement fails at runtime.

int[] myInts = new int[] {8,9};
string bar = string.Format("{0} and {1}", myInts);

Index (zero based) must be greater than or equal to zero and less than the size of the argument list.

  • Why doesn't or can't the int array be coerced or boxed to an object[] or string[]?
  • Out of a small bit of curiosity, why doesn't the compiler catch this?
+8  A: 

The call fails with the same reason the following will also fail:

string foo = string.Format("{0} {1}", 5);

You are specifying two arguments in the format but only specifying one object.

The compiler does not catch it because int[] is passed as an object which is a perfectly valid argument for the function.

Also note that array covariance does not work with value types so you cannot do:

object[] myInts = new int[] {8,9};

However you can get away with:

object[] myInts = new string[] { "8", "9" };
string bar = string.Format("{0} {1}", myInts);

which would work because you would be using the String.Format overload that accepts an object[].

João Angelo
@João: thanks for this answer. I've updated teh question to include the success of `string.Format()` with a `string[]`. Is that any different from the `int[]`?
p.campbell
@p.campbell, see my update about array covariance not being supported in value types.
João Angelo
A: 

Your string.Format is expecting 2 arguments ({0} and {1}). You are only supplying 1 argument (the int[]). You need something more like this:

string bar = string.Format("{0} and {1}", myInts[0], myInts[1]);

The compiler does not notice the problem because the format string is evaluated at runtime. IE The compiler doesn't know that {0} and {1} mean there should be 2 arguments.

msergeant
A: 

This works:

string bar = string.Format("{0} and {1}", myInts[0], myInts[1]);

The compiler doesn't catch it because it doesn't evaluate your format string.

The example you gave up top doesn't match what you're trying to do down below... you provided two {} and two arguments, but in the bottom one you only provided one argument.

Fosco
+2  A: 

Your call gets translated into this:

string foo = string.Format("{0} {1}", myInts.ToString());

which results in this string:

string foo = "System.Int32[] {1}";

So as the {1} doesn't have a parameter, it throws an exception

Michael Stum
+2  A: 

I think the concept you are having an issue with is why int[] isn't cast to object[]. Here's an example that shows why that would be bad

int[] myInts = new int[]{8,9};
object[] myObjs = (object[])myInts;
myObjs[0] = new object();

The problem is that we just added an object into a int array.

So what happens in your code is that myInts is cast to object and you don't have a second argument to fill in the {1}

juharr