How to pass a single object[] to a params object[]

124

I have a method which takes params object[] such as:

void Foo(params object[] items)
{
    Console.WriteLine(items[0]);
}

When I pass two object arrays to this method, it works fine:

Foo(new object[]{ (object)"1", (object)"2" }, new object[]{ (object)"3", (object)"4" } );
// Output: System.Object[]

But when I pass a single object[], it does not take my object[] as the first param, instead it takes its all elements like I wanted to pass them one by one:

Foo(new object[]{ (object)"1", (object)"2" });
// Output: 1, expected: System.Object[]

How do I pass a single object[] as a first argument to a params array?

This question is tagged with c# arrays

~ Asked on 2008-08-30 21:22:06

7 Answers


100

A simple typecast will ensure the compiler knows what you mean in this case.

Foo((object)new object[]{ (object)"1", (object)"2" }));

As an array is a subtype of object, this all works out. Bit of an odd solution though, I'll agree.

~ Answered on 2008-08-30 21:36:59


74

The params parameter modifier gives callers a shortcut syntax for passing multiple arguments to a method. There are two ways to call a method with a params parameter:

1) Calling with an array of the parameter type, in which case the params keyword has no effect and the array is passed directly to the method:

object[] array = new[] { "1", "2" };

// Foo receives the 'array' argument directly.
Foo( array );

2) Or, calling with an extended list of arguments, in which case the compiler will automatically wrap the list of arguments in a temporary array and pass that to the method:

// Foo receives a temporary array containing the list of arguments.
Foo( "1", "2" );

// This is equivalent to:
object[] temp = new[] { "1", "2" );
Foo( temp );


In order to pass in an object array to a method with a "params object[]" parameter, you can either:

1) Create a wrapper array manually and pass that directly to the method, as mentioned by lassevk:

Foo( new object[] { array } );  // Equivalent to calling convention 1.

2) Or, cast the argument to object, as mentioned by Adam, in which case the compiler will create the wrapper array for you:

Foo( (object)array );  // Equivalent to calling convention 2.


However, if the goal of the method is to process multiple object arrays, it may be easier to declare it with an explicit "params object[][]" parameter. This would allow you to pass multiple arrays as arguments:

void Foo( params object[][] arrays ) {
  foreach( object[] array in arrays ) {
    // process array
  }
}

...
Foo( new[] { "1", "2" }, new[] { "3", "4" } );

// Equivalent to:
object[][] arrays = new[] {
  new[] { "1", "2" },
  new[] { "3", "4" }
};
Foo( arrays );

Edit: Raymond Chen describes this behavior and how it relates to the C# specification in a new post.

~ Answered on 2008-09-01 16:28:37


9

This is a one line solution involving LINQ.

var elements = new String[] { "1", "2", "3" };
Foo(elements.Cast<object>().ToArray())

~ Answered on 2016-02-18 06:54:26


3

You need to encapsulate it into another object[] array, like this:

Foo(new Object[] { new object[]{ (object)"1", (object)"2" }});

~ Answered on 2008-08-30 21:31:28


2

Another way to solve this problem (it's not so good practice but looks beauty):

static class Helper
{
    public static object AsSingleParam(this object[] arg)
    {
       return (object)arg;
    }
}

Usage:

f(new object[] { 1, 2, 3 }.AsSingleParam());

~ Answered on 2018-04-11 15:23:54


1

One option is you can wrap it into another array:

Foo(new object[]{ new object[]{ (object)"1", (object)"2" } });

Kind of ugly, but since each item is an array, you can't just cast it to make the problem go away... such as if it were Foo(params object items), then you could just do:

Foo((object) new object[]{ (object)"1", (object)"2" });

Alternatively, you could try defining another overloaded instance of Foo which takes just a single array:

void Foo(object[] item)
{
    // Somehow don't duplicate Foo(object[]) and
    // Foo(params object[]) without making an infinite
    // recursive call... maybe something like
    // FooImpl(params object[] items) and then this
    // could invoke it via:
    // FooImpl(new object[] { item });
}

~ Answered on 2008-08-30 21:31:49


1

new[] { (object) 0, (object) null, (object) false }

~ Answered on 2012-06-21 23:37:02


Most Viewed Questions: