Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

int[] using "wrong" Console.WriteLine overload

Tags:

arrays

c#

I was working with a coworker on some basic C# tutorials and we came across what we though was an interesting conundrum.

The following code works as expected:

string[] strings = { "1", "2", "3" };
Console.WriteLine("{0}, {1}, {2}", strings);

It gets the string array and prints out the string "1, 2, 3" to the console using the Console.WriteLine(string format, params object[] arg) overload of the WriteLine method.

However the following code doesn't work:

int[] ints = { 1, 2, 3 };
Console.WriteLine("{0}, {1}, {2}", ints);

You get a FormatException with the message Index (zero based) must be greater than or equal to zero and less than the size of the argument list. Using Intellisense I can see that it is trying to use the Console.WriteLine(string format, object arg0) overload and that is why we are getting that message, it doesn't see ints as an array although it obviously is.

If we switch to the more obvious:

int[] ints = { 1, 2, 3 };
Console.WriteLine("{0},{1},{2}", ints[0], ints[1], ints[2]);

It works again and uses the params object[] overload again.

Is there a reason it does not see the int[] as an array for the method? Does the fact that Int32 is a struct make a difference? If so, why?

EDIT

I did a quick test with doubles in the same format and those didn't work as well, which makes me think that it really is the fact the type is a struct but I still do not understand why that would make a difference.

like image 526
Evan Frisch Avatar asked Jan 13 '16 19:01

Evan Frisch


2 Answers

The reason this works with string objects is Array Covariance feature of C#.

For any two reference-types A and B, if an implicit or explicit reference conversion exists from A to B, then the same reference conversion also exists from the array type A[] to the array type B[]

There is an implicit conversion from string to object, so WriteLine takes your string[] array in place of object[] array.

There is no covariance for int[], because int is not a reference type. If you would like to use an explicit conversion, you can do it like this:

object[] ints = (new int[]{ 1,2,3 }).Cast<object>().ToArray();
Console.WriteLine("{0}, {1}, {2}", ints);       

Demo.

like image 113
Sergey Kalinichenko Avatar answered Oct 20 '22 18:10

Sergey Kalinichenko


Yes, it is because int is a value-type. It's trying to find the best match. string[] is convertible to object[], but int[] is not because arrays of structs are not covariant. As a workaround, you could use

int[] ints = { 1, 2, 3 };
Console.WriteLine("{0}, {1}, {2}", ints.Cast<Object>().ToArray());
like image 21
Kyle W Avatar answered Oct 20 '22 20:10

Kyle W