将数组作为 `params` 参数传递

36
我有以下的方法:

I have the following method:

void MyMethod(params object[] args)
{
}

我试图使用类型为 object[] 的参数调用它:

object[] myArgs = GetArgs();
MyMethod(myArgs);

编译没有问题,但在MyMethod内,我写了 args == { myArgs},也就是一个只有一个元素的数组,这个元素是我的原始参数。显然我想要的是args = myArgs,我哪里做错了?

编辑:
事实上,Jon Skeet 是正确的,GetArgs() 确实将其包装在一个只有一个元素的数组中,对于这个愚蠢的问题,我感到很抱歉。


1
但是在MyMethod内部,我args == { myArgs }是什么意思?为什么不展示那段代码? - Tim Schmelter
1
问题 object[] 也是 object 啊 :) - Tony
3
@Hans: 不,这绝对不是完全正常的。发生的情况并非如此。编译器在不必要时不会创建数组。 - Jon Skeet
GetArgs() 函数是否返回一个 object[] - D Stanley
@DStanley,是的,在这种特定情况下,它会返回一个包含3个元素的object[] - Grzenio
显示剩余9条评论
2个回答

51

你所描述的情况根本不会发生。编译器只有在需要时才会创建包装数组。以下是一个简短但完整的程序,演示了这一点:

using System;

class Test
{
    static void MyMethod(params object[] args)
    {
        Console.WriteLine(args.Length);
    }

    static void Main()
    {
        object[] args = { "foo", "bar", "baz" };
        MyMethod(args);
    }
}
根据你的问题,这段代码应该输出1 - 但实际上不是,它输出3。 args 的值直接传递给了 MyMethod,没有进一步展开。
要么你的代码不是你发布的那样,要么“包装”发生在 GetArgs 中。
你可以通过将 args 强制转换为 object 来强制进行包装。例如,如果我更改 Main 的最后一行:
MyMethod((object) args);

... 然后 打印1,因为它实际上是调用 MyMethod(new object[] { args })


1
MyMethod(new int[]{1,2,3})打印出了1,那么它可能不是一个对象数组。 - Dirk
4
是的,因为int[]不是object[],所以必须将其包装起来。但这并不是OP代码所展示的情况——myArgs的编译时类型是object[]而不是int[] - Jon Skeet
1
@所有人 我认为Dirk理解这个区别,他只是提出了一个可能的原因,为什么OP的代码没有按照说明书上的那样运行。 - Adam Houldsworth
1
@peer 类型不一定要完全匹配,但元素类型必须是引用类型。例如,string[] 可以工作。 - Georg
1
@Jon 你真是个天才。我不知道怎么可能会有人获取这么多的知识。 - gmail user
显示剩余7条评论

2

以下转换对我有效:

void Foo(params object[] args)
{
  foreach (var arg in args) 
    Console.WriteLine(arg.ToString());
}

var integers = new int[]{1,2,3,4};
Foo(integers.Cast<object>().ToArray());

感谢您对Stack Overflow社区的贡献。这可能是一个正确的答案,但如果您能提供代码的额外解释,那将非常有帮助,这样开发人员就能理解您的思路。对于那些对语法不太熟悉或者正在努力理解概念的新手开发人员来说,这尤其有用。您是否可以编辑您的答案,以包含额外的细节,以造福社区? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接