Як передати один об'єкт [] об'єкту парам []


124

У мене є метод, який приймає 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?

Відповіді:


99

Простий набір даних забезпечить компілятору відомо, що ви маєте на увазі в цьому випадку.

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

Оскільки масив є підтипом об'єкта, це все працює. Хоча трохи дивного рішення, я згоден.


2
те, як парами працюють, видається непотрібним та неоптимальним c # дизайном, враховуючи те, до чого ми звикли іншими мовами. парами могли бути прийняті лише для однієї форми, і можна було б додати функцію, подібну до поширення, яка буде корисною для всієї мови, а не лише для цього випадку. наприклад, ми можемо змусити всі виклики парам бути Foo (obj [0], obj [1]), а потім мати окремий оператор розповсюдження, що дозволяє Foo (... obj).
Уїтніленд

1
зрозумів, що я не дав зрозуміти, що я дуже поважаю Андерса Хейльсберга, він один з найкращих мовних дизайнерів у світі. але ми можемо подумати про вдосконалення роботи будь-кого з урахуванням достатньої задля огляду, отже, технологій.
Уїтніленд

74

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, як згадував Адам , і тоді компілятор створить для вас масив обгортки:

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

Це однолінійне рішення за участю LINQ.

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

3

Вам потрібно інкапсулювати його в інший масив об’єктів [], як це:

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

2

Ще один спосіб вирішити цю проблему (це не так добре, але красиво виглядає):

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

Використання:

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

1

Один із варіантів - ви можете зафіксувати його в іншому масиві:

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

Вигляд некрасивий, але оскільки кожен елемент - це масив, ви не можете просто надати його, щоб усунути проблему ... наприклад, якщо це Foo (параметри об'єктних елементів), ви можете просто зробити:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.