2014-11-06 7 views
6

Als ich mit params experimentierte, bemerkte ich die MS-Dokumentation sagt, wenn Sie ein Array von int als Methode Parameter übergeben, der eine Signatur von params object[] myParam hat, wird es ein mehrdimensionales Array. Aber ich habe festgestellt, wenn Sie ein Array von objects[] oder strings[] übergeben es nicht. Dies scheint, als wäre es ein Kopfschmerz, mit zu arbeiten, wie Sie für Multi-Dim-Arrays überprüfen müssen.Warum wird das Array param object [] gezackt, wenn Sie ein Array int [] übergeben?

See MSDN link

Beispiel:

public static void UsingParams(params object[] myParam) 
{ 
    //Code to return myParam 
} 

//myParam[0][0] = {1, 2}, multi-dimensional 
int[] myIntArray = {1, 2}; 
UsingParams(myIntArray); 

//myParam[0] = {"1", "2"}, single-dimensional 
string[] myStrArray = {"1", "2"}; 
UsingParams(myStrArray); 

Warum tritt das?

+1

Das ist kein multidimensionales Array. – Servy

+0

Ich denke vielleicht in Bezug auf PHP - erleuchte mich? – johnjk07

+1

@Servy ist korrekt. Es ist eigentlich ein Array, das ein anderes Array als erstes Element hat. – artokai

Antwort

14

Jedes Mal, wenn Sie einen params Parameter haben der Compiler versucht, ein Array zu akzeptieren alle Werte für das params Argument darstellt, wenn der Parameter an der fraglichen Stelle ist in diesem Kontext gültig.Wenn es nicht der Fall ist, wird versucht, es als ein Element in dem Array params Werte zu behandeln, und nicht als das gesamte Array.Wenn es das auch nicht kann, wird es fehlschlagen

In Ihrem zweiten Beispiel kann eine string[] implizit in eine object[] konvertiert werden, so wird es als die übergeben gesamte Liste der Parameter. Diese implizite Konvertierung ist aufgrund der Array-Kovarianz gültig.

In Ihrem ersten Beispiel kann die int[] nicht implizit in eine object[] konvertiert werden (Array-Kovarianz ist auf Referenztypen beschränkt), daher wird sie als ein Wert im Array behandelt. Ein int[]kann implizit in object konvertiert werden, so was übergeben wird, ist ein Objekt-Array mit einem int[] als sein einziges Element. Beachten Sie, dass sich ein Array mit einem anderen Array als Element grundlegend von einem mehrdimensionalen Array unterscheidet.

+1

Ich sehe - also der einzige Grund, warum 'object []' und 'string []' arbeiten, ist wegen impliziter Konvertierung Unterstützung. Wenn ich ein Array von Ganzzahlen übergeben will, kann ich sie einfach als 'Objekt []' übergeben. Ich versuche, mich mit den tatsächlichen Produktcode-Konsequenzen davon auseinanderzusetzen. – johnjk07

+0

@ user209718 Wenn Sie explizit ein 'object []' erstellen, das zufällig ganze Zahlen enthält, dann wird yes als die gesamte Liste der 'params' Werte behandelt, nicht nur die erste. – Servy

+2

@ johnjk07 Sie würden Generika verwenden, um Boxen in der realen Welt zu vermeiden. Die Verwendung von 'object' zum Übergeben mehrerer Datentypen ist eine schlechte Übung (obwohl es einige gültige Anwendungsfälle gibt).Generics existieren, um Boxen/Unboxing zu vermeiden. – Haney

2

C# versucht herauszufinden, wenn Sie nur einen Wert an ein params Argument übergeben, ob Sie meinen, dass dieser Wert das durch das Argument dargestellte Array ist oder ob Sie das erste Argument eines größeren übergeben Array.

Wenn Sie das params Schlüsselwort entfernen, werden Sie sehen, dass int[] nicht direkt in eine object[] (aufgrund int ist ein Nicht-Referenz-Typ) umgewandelt werden:

enter image description here

So Zahlen C# muss es Sei nur der erste deiner Paramis, den du durchläufst, und nicht das gesamte Array. Er wandelt den Code dazu:

int[] myIntArray = {1, 2}; 
UsingParams(new object[]{myIntArray}); 
+0

Dies erklärt in keiner Weise den Unterschied zwischen den beiden ex Ahlen gezeigt. Darüber hinaus wird der Compiler immer versuchen, einen bereitgestellten Parameter als das gesamte Array und nicht als einen Wert in dem Array zu übergeben, wenn es möglich ist. – Servy

+0

@Servy: Entschuldigung, ich hatte das noch nicht vollständig ausgearbeitet. Was denkst du über mein Update? – StriplingWarrior

+0

@StriplingWarrior, danke für den Test und die Klärung. Es macht Sinn. – johnjk07

1

Grundsätzlich Ihre Methodensignatur ein oder mehr Objekte zu nehmen und sie in ein Array myParam genannt zu konsolidieren. Wenn mehrere Objekte einzeln übergeben werden, z. B. der Aufruf UsingParams(1, "hello", ...), werden sie automatisch in das Array object[] konvertiert. Dies ist ein Compiler Trick/syntaktischer Zucker.

Wenn das übergebene Objekt kein object[] Array oder eine Liste einzelner Objekte ist, wird es das erste Argument Ihres Arrays. Mit anderen Worten, wenn Sie eine int[] übergeben, dann wird Ihr myParam ein Array sein, dessen erstes Element ebenfalls ein Array ist, was es zu einem gezackten Array macht. Dies liegt daran, int[] ist ein object und der Compiler ist nicht schlau genug, um herauszufinden, was Sie tun, und macht es zum einzigen Element der object[] Array. Es gibt keine implizite Umwandlung von int[] zu object[] und deshalb passiert es nicht.

Das einzige Mal, können Sie ein Array übergeben, die bevölkert wird, wie man es erwarten würde, wenn die Array-Typ object[] ist, wie new object[] { 1, "hello", ... } oder die Array-Typ ist covariant. In diesem Fall ist ein string[] Array kovariant und kann implizit in einen object[] umgewandelt werden, während ein int[] nicht kann.

Zusammengefasst:

UsingParams(1, "hello") = gut

UsingParams(new object[] { 1, "hello" }) = gut

UsingParams(new string[] { "hi", "hello" }) = gut (wegen Matrixkovarianz)

UsingParams(new int[] { 1, 2 }) = schlecht (kein Matrixkovarianz), wird ein gezacktes Array sein

Further reading on array covariance rules, die auch zitiert: "Array-Kovarianz erstreckt sich nicht speziell auf Arrays von Werttypen. Zum Beispiel gibt es keine Konvertierung, dass ein int[] als object[] behandelt werden erlaubt.“

+0

'Die einzige Zeit, die Sie ein Array übergeben können, das wie erwartet gefüllt wird, ist, wenn dieser Array-Typ Objekt [] ist, z. B. neues Objekt [] {1," Hallo ", ...}' Das OP ist das zweite Beispiel beweist, dass dies falsch ist. – Servy

+0

@Servy 'string []' ist nicht 'object []', obwohl 'string: object' – Haney

+2

Aufgrund der Array-Kovarianz (und ihrer Abhängigkeit von Referenztypen) ist eine' string [] '* * ein 'object []', aber ein 'int []' ist nicht. Diese Tatsache erklärt den Unterschied im Verhalten der beiden Beispiele. – Servy

Verwandte Themen