我正在和一位同事一起学习一些基本的C#教程,我们遇到了一个有趣的难题。
以下代码按预期工作:
string[] strings = { "1", "2", "3" };
Console.WriteLine("{0}, {1}, {2}", strings);
它获取字符串数组,并使用Console.WriteLine(string format, params object[] arg)
方法的WriteLine
重载将字符串“1,2,3”打印到控制台。
但是以下代码不起作用:
int[] ints = { 1, 2, 3 };
Console.WriteLine("{0}, {1}, {2}", ints);
您收到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]);
它再次起作用并再次使用params object[]
重载。
是否有理由不将int[]
视为该方法的数组? Int32
是一个结构的事实是否会产生影响?如果是这样,为什么?
修改
我用相同格式的双打进行了快速测试,但那些效果不好,这让我觉得这个类型是一个结构,但我仍然不明白为什么会产生影响
答案 0 :(得分:8)
这适用于string
个对象的原因是C#的Array Covariance功能。
对于任何两种引用类型
的数组类型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);
答案 1 :(得分:5)
是的,这是因为int
是值类型。它试图找到最佳匹配。 string[]
可转换为object[]
,但int[]
不是因为结构数组不是协变的。作为解决方法,您可以使用
int[] ints = { 1, 2, 3 };
Console.WriteLine("{0}, {1}, {2}", ints.Cast<Object>().ToArray());