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.
The reason this works with string
objects is Array Covariance feature of C#.
For any two reference-types
A
andB
, if an implicit or explicit reference conversion exists fromA
toB
, then the same reference conversion also exists from the array typeA[]
to the array typeB[]
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.
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());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With