Как передать один объект [] объекту params []

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

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?

Ответ 1

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

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

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

Ответ 2

Модификатор параметра 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 );

Изменить: Раймонд Чен описывает это поведение и как он относится к спецификации С# в новом сообщении.

Ответ 3

Это однолинейное решение, включающее LINQ.

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

Ответ 4

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

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

Ответ 5

Один из вариантов - вы можете перенести его в другой массив:

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

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

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

Ответ 6

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