2008-08-30 9 views
104

J'ai une méthode qui prend un objet params [] tels que:Comment passer un seul objet [] à un objet params []

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

Quand je passe deux tableaux d'objets à cette méthode, il fonctionne très bien :

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

Mais quand je passe un seul objet [], il ne prend pas mon objet [] comme le premier paramètre, au lieu qu'il le prend tous les éléments que je voulais les passer un par un:

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

Comment transmettre un seul objet [] en tant que premier argument à un tableau params?

Répondre

82

Une conversion de type simple, assurera le compilateur sait ce que vous entendez dans ce cas.

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

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

+0

la façon dont params œuvres semble inutile, et la conception suboptimale C#, étant donné ce que nous sommes habitués dans d'autres langues. params aurait pu être fait pour n'accepter qu'un seul formulaire, et une fonctionnalité similaire à la propagation pourrait être ajoutée, ce qui serait bénéfique pour l'ensemble de la langue, pas seulement pour ce cas. Par exemple, nous pourrions forcer tous les appels de paramètres à être Foo (obj [0], obj [1]), et avoir un opérateur de propagation séparé permettant Foo (... obj). – Lee

+0

réalisé je n'avais pas précisé que j'ai un grand respect pour anders hejlsberg, il est l'un des meilleurs concepteurs de la langue dans le monde. mais nous pouvons penser à des améliorations au travail de n'importe qui avec assez de recul, d'où la technologie. – Lee

3

Vous devez encapsuler dans un autre objet [] tableau, comme ceci:

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

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

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

Type de laid, mais depuis 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 (objets objets params), alors vous pouvez 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 prend 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 }); 
} 
61

Le modificateur de paramètre params donne aux appelants une syntaxe de raccourci pour transmettre plusieurs arguments à une méthode.Il y a deux façons d'appeler une méthode avec un paramètre params:

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

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

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

2) Ou, appelant une liste étendue d'arguments, dans ce cas, le compilateur se terminera automatiquement la liste des arguments dans un tableau temporaire et que passer à 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 dans un tableau d'objet à une méthode avec un paramètre « params object[] », vous pouvez:

1) créer une matrice d'enveloppe manuellement et passe que directement à la procédé, tel que mentionné par lassevk:

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

2) Or, l'argument de coulée object, comme mentionné par Adam, auquel cas le compilateur crée le tableau d'emballage pour vous:

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


Cependant, si l'objectif de la méthode consiste à traiter plusieurs tableaux d'objets, il peut être plus facile de déclarer avec un paramètre explicite "params object[][]". Cela vous permettra 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); 

Edit: Raymond Chen décrit ce comportement et la façon dont elle se rapporte à la spécification C# dans a new post.

1
new[] { (object) 0, (object) null, (object) false } 
7

Ceci est une solution d'une ligne impliquant LINQ.

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