Domanda

Ho un metodo che accetta params object[] come:

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

Quando passo due array di oggetti a questo metodo, funziona correttamente:

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

Ma quando passo un singolo oggetto[], non prende il mio oggetto[] come primo parametro, ma prende invece tutti gli elementi come se volessi passarli uno per uno:

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

Come posso passare un singolo oggetto[] come primo argomento a un array params?

È stato utile?

Soluzione

Un semplice typecast garantirà che il compilatore sappia cosa intendi in questo caso.

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

Poiché un array è un sottotipo di oggetto, tutto funziona.Una soluzione un po' strana però, sono d'accordo.

Altri suggerimenti

IL params il modificatore di parametro fornisce ai chiamanti una sintassi di scelta rapida per passare più argomenti a un metodo.Esistono due modi per chiamare un metodo con a params parametro:

1) Chiamando con un array del tipo parametro, nel qual caso the params la parola chiave non ha alcun effetto e l'array viene passato direttamente al metodo:

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

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

2) Oppure, chiamando con un elenco esteso di argomenti, nel qual caso il compilatore avvolgerà automaticamente l'elenco di argomenti in un array temporaneo e lo passerà al metodo:

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

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


Per passare un array di oggetti a un metodo con un "params object[]", puoi:

1) Crea manualmente un array wrapper e passalo direttamente al metodo, come menzionato da lassevk:

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

2) Oppure, lancia l'argomento a object, come menzionato da Adamo, nel qual caso il compilatore creerà l'array wrapper per te:

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


Tuttavia, se l'obiettivo del metodo è elaborare più array di oggetti, potrebbe essere più semplice dichiararlo con un "params object[][]"parametro.Ciò ti consentirebbe di passare più array come argomenti:

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

Modificare: Raymond Chen descrive questo comportamento e la sua relazione con la specifica C# in un nuovo post.

Questa è una soluzione a una riga che coinvolge LINQ.

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

Devi incapsularlo in un altro array object[], in questo modo:

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

Un'opzione è che puoi avvolgerlo in un altro array:

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

Un po' brutto, ma dal momento che ogni elemento è un array, non puoi semplicemente lanciarlo per risolvere il problema...come se fosse Foo(params object items), allora potresti semplicemente fare:

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

In alternativa, potresti provare a definire un'altra istanza sovraccaricata di Foo che accetta solo un singolo array:

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 }

Un altro modo per risolvere questo problema (non è una buona pratica ma sembra bello):

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

Utilizzo:

f(new object[] { 1, 2, 3 }.AsSingleParam());
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top