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

StackOverflow https://stackoverflow.com/questions/36350

  •  09-06-2019
  •  | 
  •  

Вопрос

У меня есть метод, который принимает параметры 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[]

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

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

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

Это было полезно?

Решение

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

Foo((object)new object[]{ (object)"1", (object)"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) Создайте массив-оболочку вручную и передайте его непосредственно методу, как указано в лассевк:

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

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

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 #, в новая должность.

Это однолинейное решение с использованием LINQ.

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

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

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

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

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 });
}
new[] { (object) 0, (object) null, (object) false }

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

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

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

f(new object[] { 1, 2, 3 }.AsSingleParam());
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top