如果将int []数组传入其中,为什么param object []数组会变成锯齿状?

时间:2014-11-06 20:11:13

标签: c# arrays params

在我试验params时,我注意到MS文档说如果您将int数组作为方法参数传递,其签名为params object[] myParam,它将成为多维数组。但是我注意到,如果你传递的是objects[]strings[]的数组,那么它就没有。这似乎很难处理,因为你必须检查多维数组。

See MSDN link

示例:

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);

为什么会这样?

3 个答案:

答案 0 :(得分:14)

每当有params参数时,如果相关位置的参数在该上下文中有效,编译器将尝试接受表示params参数的所有值的数组。如果不是,那么它会尝试将其视为params值数组中的一个项,而不是整个数组。如果它不能这样做那么它将无法编译。

在第二个示例中,string[]可以隐式转换为object[],因此它将作为整个参数列表传递。由于数组协方差,这种隐式转换是有效的。

在第一个示例中,int[]无法隐式转换为object[](数组协方差仅限于引用类型),因此它被视为数组中的一个值。 int[] 可以隐式转换为object,因此传递的是一个包含int[]作为唯一项目的对象数组。请注意,将另一个数组作为项目的数组与多维数组明显不同。

答案 1 :(得分:2)

当你只将一个值传递给params参数时,C#试图弄明白,是否意味着该值是参数所代表的数组,或者你是否将第一个参数传递给它一个更大的阵列。

如果您删除params关键字,则会看到int[]无法直接转换为object[](由于int是非引用类型) :

enter image description here

所以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[]的转换。"