Как передать один объект [] объекту 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 }