在我试验params
时,我注意到MS文档说如果您将int
数组作为方法参数传递,其签名为params object[] myParam
,它将成为多维数组。但是我注意到,如果你传递的是objects[]
或strings[]
的数组,那么它就没有。这似乎很难处理,因为你必须检查多维数组。
示例:
public static void UsingParams(params object[] myParam)
{
//Code to return myParam
}
//myParam[0][0] = {1, 2}, multi-dimensional
int[] myIntArray = {1, 2};
UsingParams(myIntArray);
//myParam[0] = {"1", "2"}, single-dimensional
string[] myStrArray = {"1", "2"};
UsingParams(myStrArray);
为什么会这样?
答案 0 :(得分:14)
每当有params
参数时,如果相关位置的参数在该上下文中有效,编译器将尝试接受表示params
参数的所有值的数组。如果不是,那么它会尝试将其视为params
值数组中的一个项,而不是整个数组。如果它不能这样做那么它将无法编译。
在第二个示例中,string[]
可以隐式转换为object[]
,因此它将作为整个参数列表传递。由于数组协方差,这种隐式转换是有效的。
在第一个示例中,int[]
无法隐式转换为object[]
(数组协方差仅限于引用类型),因此它被视为数组中的一个值。 int[]
可以隐式转换为object
,因此传递的是一个包含int[]
作为唯一项目的对象数组。请注意,将另一个数组作为项目的数组与多维数组明显不同。
答案 1 :(得分:2)
当你只将一个值传递给params
参数时,C#试图弄明白,是否意味着该值是参数所代表的数组,或者你是否将第一个参数传递给它一个更大的阵列。
如果您删除params
关键字,则会看到int[]
无法直接转换为object[]
(由于int
是非引用类型) :
所以C#表示它必须只是你传入的第一个参数,而不是整个数组。它将您的代码转换为:
int[] myIntArray = {1, 2};
UsingParams(new object[]{myIntArray});
答案 2 :(得分:1)
基本上,您的方法签名会占用一个或多个对象,并将它们合并到一个名为myParam
的数组中。
如果单独传递多个对象(例如调用UsingParams(1, "hello", ...)
),它们将自动转换为object[]
数组。这是一个编译器技巧/语法糖。
如果传递的对象不是object[]
数组或单个对象列表,它将成为数组的第一个参数。换句话说,如果你传递int[]
,那么你的myParam
将是一个数组,其中第一个元素也是一个数组,使其成为一个锯齿状数组。这是因为int[]
是object
,并且编译器不够聪明,无法弄清楚您正在做什么,并使其成为object[]
数组的唯一元素。 int[]
到object[]
没有隐式广告,这就是为什么它没有发生。
您唯一可以传递将按照您预期填充的数组的时间是该数组类型为object[]
,例如new object[] { 1, "hello", ... }
或数组类型为协变。在这种情况下,string[]
数组是协变的,可以隐式转换为object[]
而int[]
不能。{/ p>
总结:
UsingParams(1, "hello")
=好
UsingParams(new object[] { 1, "hello" })
=好
UsingParams(new string[] { "hi", "hello" })
=好(由于数组协方差)
UsingParams(new int[] { 1, 2 })
=坏(没有数组协方差),将是一个锯齿状数组
Further reading on array covariance rules也引用:"数组协方差特别没有扩展到值类型的数组。例如,不存在允许int[]
被视为object[]
的转换。"