Question

J'ai une méthode qui prend des paramètres object[] tels que :

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

Lorsque je passe deux tableaux d'objets à cette méthode, cela fonctionne correctement :

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

Mais lorsque je passe un seul objet[], il ne prend pas mon objet[] comme premier paramètre, mais prend tous ses éléments comme si je voulais les transmettre un par un :

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

Comment passer un seul objet[] comme premier argument à un tableau de paramètres ?

Était-ce utile?

La solution

Un simple transtypage garantira que le compilateur sait ce que vous voulez dire dans ce cas.

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

Comme un tableau est un sous-type d’objet, tout cela fonctionne.Une solution un peu étrange cependant, je suis d'accord.

Autres conseils

Le params Le modificateur de paramètre donne aux appelants une syntaxe de raccourci pour transmettre plusieurs arguments à une méthode.Il existe deux manières d'appeler une méthode avec un params paramètre:

1) Appel avec un tableau du type paramètre, auquel cas le params Le mot-clé n'a aucun effet et le tableau est passé directement à la méthode :

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

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

2) Ou, en appelant avec une liste étendue d'arguments, auquel cas le compilateur encapsulera automatiquement la liste d'arguments dans un tableau temporaire et la transmettra à la méthode :

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

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


Afin de passer un tableau d'objets à une méthode avec un "params object[]", vous pouvez soit :

1) Créez manuellement un tableau wrapper et transmettez-le directement à la méthode, comme mentionné par lassevk:

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

2) Ou, lancez l'argument à object, comme le mentionne Adam, auquel cas le compilateur créera le tableau wrapper pour vous :

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


Cependant, si le but de la méthode est de traiter plusieurs tableaux d'objets, il peut être plus facile de la déclarer avec un " " explicite.params object[][]" paramètre.Cela vous permettrait de passer plusieurs tableaux comme arguments :

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

Modifier: Raymond Chen décrit ce comportement et son lien avec la spécification C# dans un nouveau message.

Il s'agit d'une solution en une seule ligne impliquant LINQ.

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

Vous devez l'encapsuler dans un autre tableau object[], comme ceci :

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

Une option est que vous pouvez l'envelopper dans un autre tableau :

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

Un peu moche, mais comme chaque élément est un tableau, vous ne pouvez pas simplement le lancer pour faire disparaître le problème...comme s'il s'agissait de Foo (éléments d'objet params), alors vous pourriez simplement faire :

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

Alternativement, vous pouvez essayer de définir une autre instance surchargée de Foo qui ne prend qu'un seul tableau :

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 }

Une autre façon de résoudre ce problème (ce n'est pas une très bonne pratique mais ça a l'air beau) :

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

Usage:

f(new object[] { 1, 2, 3 }.AsSingleParam());
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top