我正在和一位同事一起学习一些基本的C#教程,我们遇到了一个有趣的难题.
以下代码按预期工作:
string[] strings = { "1", "2", "3" };
Console.WriteLine("{0}, {1}, {2}", strings);
Run Code Online (Sandbox Code Playgroud)
它获取字符串数组并使用方法的Console.WriteLine(string format, params object[] arg)重载将字符串"1,2,3"打印到控制台WriteLine.
但是,以下代码不起作用:
int[] ints = { 1, 2, 3 };
Console.WriteLine("{0}, {1}, {2}", ints);
Run Code Online (Sandbox Code Playgroud)
你得到一个FormatException消息Index (zero based) must be greater than or equal to zero and less than the size of the argument list.使用Intellisense我可以看到它正在尝试使用Console.WriteLine(string format, object arg0)重载,这就是为什么我们得到那个消息,它看起来不像ints一个数组,虽然它显然是.
如果我们切换到更明显的:
int[] ints = { 1, 2, 3 };
Console.WriteLine("{0},{1},{2}", ints[0], ints[1], ints[2]);
Run Code Online (Sandbox Code Playgroud)
它再次工作并再次使用params object[]过载.
有没有理由它没有看到该int[]方法的数组?Int32作为结构的事实是否有所作为?如果是这样,为什么?
编辑
我用相同格式的双打进行了快速测试,但那些效果并不好,这让我觉得它确实是类型是结构的事实,但我仍然不明白为什么会产生影响.
这与string对象一起使用的原因是C#的数组协方差特性.
对于任何两个引用类型
A和B,如果隐式或显式引用转换从存在A到B,则相同的参考转换同时从阵列型存在A[]于阵列类型B[]
有从隐式转换string到object,所以WriteLine需要你的string[]阵列代替object[]阵列.
没有协方差int[],因为int它不是引用类型.如果您想使用显式转换,可以这样做:
object[] ints = (new int[]{ 1,2,3 }).Cast<object>().ToArray();
Console.WriteLine("{0}, {1}, {2}", ints);
Run Code Online (Sandbox Code Playgroud)
是的,这是因为int是一种价值型.它试图找到最佳匹配. string[]可以转换为object[],但int[]不是因为结构数组不是协变的.作为一种解决方法,您可以使用
int[] ints = { 1, 2, 3 };
Console.WriteLine("{0}, {1}, {2}", ints.Cast<Object>().ToArray());
Run Code Online (Sandbox Code Playgroud)