Как передать один объект [] в объект params [] - PullRequest
117 голосов
/ 31 августа 2008

У меня есть метод, который принимает params object [], например:

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

Когда я передаю два массива объектов этому методу, он отлично работает:

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

Но когда я передаю один объект [], он не принимает мой объект [] в качестве первого параметра, вместо этого он принимает все его элементы, как я хотел передать их один за другим:

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

Как передать один объект [] в качестве первого аргумента в массив params?

Ответы [ 7 ]

94 голосов
/ 31 августа 2008

Простой набор типов гарантирует, что компилятор знает, что вы имеете в виду в этом случае.

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

Поскольку массив является подтипом объекта, все это работает. Немного странное решение, хотя, я согласен.

69 голосов
/ 01 сентября 2008

Модификатор параметра params предоставляет вызывающим сторонам сокращенный синтаксис для передачи нескольких аргументов методу. Есть два способа вызвать метод с параметром params:

1) Вызов с массивом типа параметра, в этом случае ключевое слово params не действует, и массив передается непосредственно методу:

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

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

2) Или вызов с расширенным списком аргументов, и в этом случае компилятор автоматически обернет список аргументов во временный массив и передаст его методу:

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

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


Чтобы передать массив объектов методу с параметром "params object[]", вы можете:

1) Создать массив оберток вручную и передать его непосредственно методу, как указано в lassevk :

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

2) Или приведите аргумент к object, как указано Adam , и в этом случае компилятор создаст для вас массив-оболочку:

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


Однако, если целью метода является обработка нескольких объектных массивов, может быть проще объявить его с явным параметром "params object[][]". Это позволит вам передавать несколько массивов в качестве аргументов:

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

Редактировать: Раймонд Чен описывает это поведение и его отношение к спецификации C # в новом посте .

8 голосов
/ 18 февраля 2016

Это однолинейное решение с участием LINQ.

var elements = new String[] { "1", "2", "3" };
Foo(elements.Cast<object>().ToArray())
3 голосов
/ 31 августа 2008

Вам необходимо инкапсулировать его в другой массив object [], например:

Foo(new Object[] { new object[]{ (object)"1", (object)"2" }});
1 голос
/ 11 апреля 2018

Еще один способ решить эту проблему (это не очень хорошая практика, но выглядит красиво):

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

Использование:

f(new object[] { 1, 2, 3 }.AsSingleParam());
1 голос
/ 22 июня 2012
new[] { (object) 0, (object) null, (object) false }
1 голос
/ 31 августа 2008

Один вариант - вы можете заключить его в другой массив:

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

Довольно уродливо, но так как каждый элемент является массивом, вы не можете просто привести его, чтобы устранить проблему ... например, если это был Foo (params object items), тогда вы могли бы просто сделать:

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

В качестве альтернативы, вы можете попробовать определить другой перегруженный экземпляр Foo, который занимает всего один массив:

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 });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...