2016-01-13 16 views
9

Ich arbeitete mit einem Mitarbeiter an einigen grundlegenden C# -Tutorials und wir stießen auf was wir waren ein interessantes Rätsel.int [] mit "falsch" Console.WriteLine Überladung

Der folgende Code arbeitet, wie erwartet:

string[] strings = { "1", "2", "3" }; 
Console.WriteLine("{0}, {1}, {2}", strings); 

Es wird das String-Array und druckt die Zeichenfolge "1, 2, 3" an die Konsole, um die Überlastung der Console.WriteLine(string format, params object[] arg)WriteLine Methode.

jedoch der folgende Code nicht funktioniert:

int[] ints = { 1, 2, 3 }; 
Console.WriteLine("{0}, {1}, {2}", ints); 

Sie eine FormatException erhalten mit der Nachricht Index (zero based) must be greater than or equal to zero and less than the size of the argument list. Mit Intellisense kann ich sehen, dass es die Console.WriteLine(string format, object arg0) Überlastung zu verwenden versucht, und deshalb bekommen wir, dass Nachricht, sieht es nicht ints als Array, obwohl es offensichtlich ist.

Wenn wir wechseln auf die offensichtlicheren:

int[] ints = { 1, 2, 3 }; 
Console.WriteLine("{0},{1},{2}", ints[0], ints[1], ints[2]); 

Es funktioniert wieder und verwendet die params object[] Überlastung wieder.

Gibt es einen Grund, warum es die int[] nicht als Array für die Methode sieht? Ist die Tatsache, dass Int32 eine Struktur ist, ein Unterschied? Wenn ja warum?

EDIT

Ich habe einen schnellen Test mit Doppel im gleichen Format und jene nicht so gut arbeiten, die ich denken lassen, dass es wirklich die Tatsache, ist der Typ eine Struktur ist, aber ich noch tun verstehe nicht, warum das einen Unterschied machen würde.

+7

verwenden Es gibt implizite Konvertierung 'string []' -> 'Objekt []'. Es gibt keine solche Umwandlung für 'int []' -> 'object []'. Und ja, weil 'int' Wert ist. – PetSerAl

+0

Lesen [this] (https://msdn.microsoft.com/en-us/library/aa664572 (v = vs.71) .aspx) – dotctor

+0

Mögliches Duplikat von [Casting int \ [\] to object \ [\] ] (http://stackoverflow.com/questions/222211476/casting-int-to-object) – dotctor

Antwort

8

Der Grund, warum dies mit string Objekte funktioniert, ist Array Covariance Feature von C#.

Für irgendwelche zwei Referenztypen A und B, wenn eine implizite oder explizite Referenz Umwandlung von A zu B existiert, dann wird die gleichen Bezugsumsetzungs bestehen auch aus dem Array-Typ A[] an den Array-Typ B[]

Es gibt eine implizite Konvertierung von string zu object, so dass WriteLine Ihr string[] Array anstelle von object[] Array übernimmt.

Es gibt keine Kovarianz für int[], weil intist nicht ein Referenztyp. Wenn Sie möchten, dass eine explizite Konvertierung verwenden, können Sie es wie folgt tun:

object[] ints = (new int[]{ 1,2,3 }).Cast<object>().ToArray(); 
Console.WriteLine("{0}, {1}, {2}", ints);  

Demo.

+0

Oder einfach 'object [] ints = {1, 2, 3};' –

+0

@PatrykSpytkowski Nun, die Idee war zu demonstrieren Wie Sie mit einem Array von Primitiven beginnen und mit einem Array von "Objekten" enden, aber Ihre Syntax ist definitiv prägnanter. – dasblinkenlight

5

Ja, es ist so, weil int ein Wert-Typ ist. Es versucht, die beste Übereinstimmung zu finden. string[] ist in object[] konvertierbar, aber int[] ist nicht, weil Arrays von Strukturen nicht kovariant sind.Als Workaround könnten Sie

int[] ints = { 1, 2, 3 }; 
Console.WriteLine("{0}, {1}, {2}", ints.Cast<Object>().ToArray()); 
+0

Genauer gesagt ist 'int []' ein Array-Typ (Array-Typen sind Referenztypen), dessen Elementtyp 'int' ein Werttyp ist, und die Array-Kovarianz funktioniert nicht, wenn der Elementtyp ein Werttyp ist. ] 'ist nicht in' object [] 'konvertierbar. –