Ist int [] ein Referenztyp oder ein Werttyp?

124

Ich weiß, dass ein int ein Werttyp ist, aber was sind Arrays von Werttypen? Referenztypen? Werttypen? Ich möchte ein Array an eine Funktion übergeben, um etwas zu überprüfen. Sollte ich nur das Array übergeben, da es nur die Referenz davon übergeben wird, oder sollte ich es als ref übergeben?

verschlungenes Elysium
quelle
11
In Zukunft können Sie überprüfen, ob etwas als Referenz oder als Wert übergeben wird, indem Sie eine Variable erstellen, diese Variable an eine Methode übergeben, die diese Variable ändert, und überprüfen, welchen Wert diese Variable hat, nachdem sie die Methode durchlaufen hat. Wenn es das gleiche ist, wird es als Wert übergeben, anders, als Referenz übergeben.
11
@ darkassassin93: Die Übergabe als Referenz oder als Wert hängt nicht davon ab, ob es sich bei etwas um einen Referenztyp oder einen Werttyp handelt. (Werttypen können als Referenz übergeben werden und Referenztypen können als Wert übergeben werden.)
LukeH
2
In den meisten Fällen können Sie davon ausgehen, dass es sich um einen Referenztyp handelt, wenn Sie [null] in einem Feld oder einer Variablen speichern können. Die Ausnahmen sind sicherlich nullbare Typen (Nullable <int> oder int?) Sowie Zeichenfolgen.
Noel Widmer
3
@ NoëlWidmer Strings sind keine Ausnahme: Sie sind Ref-Typen.
Arthur Castro
2
@ArthurCastro Argument auf 50%: Zeichenfolgen erben von der Klasse, dh sie sind Referenztypen. Ihre Gleichheit basiert jedoch eher auf Identität (Wertevergleich) als auf Referenz, und ihr Übergabeverhalten wird überschrieben, um dem Verhalten von Werttypen zu entsprechen. Grundsätzlich handelt es sich per Definition um Referenztypen, die sich jedoch durch Implementierung eher wie Werttypen verhalten.
Noel Widmer

Antworten:

201

Arrays sind Mechanismen, mit denen Sie mehrere Elemente als eine einzige Sammlung behandeln können. Die Microsoft® .NET Common Language Runtime (CLR) unterstützt eindimensionale Arrays, mehrdimensionale Arrays und gezackte Arrays (Arrays von Arrays). Alle Array-Typen werden implizit von System.Array abgeleitet, das selbst von System.Object abgeleitet ist. Dies bedeutet, dass alle Arrays immer Referenztypen sind, die auf dem verwalteten Heap zugewiesen sind, und die Variable Ihrer App einen Verweis auf das Array und nicht auf das Array selbst enthält.

https://msdn.microsoft.com/en-us/library/bb985948.aspx

Yannick Motton
quelle
54
Werttypen erben von System.ValueType, das selbst von System.Object erbt. Nur weil Array von System.Object abgeleitet ist, bedeutet dies nicht, dass es sich um einen Referenztyp handelt. Was System.Array zu einem Referenztyp macht, ist, dass seine Instanzen durch Referenz kopiert werden. IOW, konzentrieren Sie sich auf die Tatsache, dass System.Array eine Klasse ist. Das macht es zu einem Referenztyp.
P.Brian.Mackey
8
<nitpick> Ich weiß, dass die Dokumentation möglicherweise impliziert, dass System.Array, das von System.Object abgeleitet ist, es zu einem Referenztyp macht. Obwohl es möglicherweise nicht wahr ist, dass ein von System.Object abgeleiteter Typ ein Referenztyp ist, ist die einzige Ausnahme von dieser Regel System.ValueType, das vom Compiler anders behandelt wird. </ Nitpick>
Yannick Motton
Der obige Link ist defekt. Hier ist ein weiterer msdn-Link, der die Vererbungshierarchie von System.Array zeigt: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N
Alles, was von System.Object abgeleitet ist, ist ein Referenztyp, es sei denn, es leitet sich auch von System.ValueType ab. @ P.Brian.Mackey Nur weil ein Typ eine Klasse ist, heißt das nicht, dass es ein Referenztyp ist, denn hinter den Kulissen sind Strukturen nur Klassen, die von System.ValueType abgeleitet sind.
David Klempfner
31

Der einfachste Test für Referenztyp vs. Werttyp ist, dass Referenztypen sein können null, Werttypen jedoch nicht.

Alex Reitbort
quelle
46
... mit Ausnahme von Nullable - Wertetypen, die auf NULL festlegbare sind (Sie den Wert auf Null gesetzt, die den Nullwert für den Typen bedeutet , anstatt eine Null - Referenz ) und sind nach wie vor Werttypen.
Jon Skeet
1
Ich hätte nie gedacht, das zu tun, wenn ich versuchen zu verstehen, ob es sich um Werttypen handelt oder nicht! Großartige Idee.
verschlungenes Elysium
6

Zuerst möchte ich Ihnen sagen, dass Array ein Referenztyp ist. Warum? Ich erkläre hier ein Beispiel.

Beispiel:

int val = 0; // this is a value type ok
int[] val1 = new int[20] // this is a reference type because space required to store 20 integer value that make array allocated on the heap.

Auch Referenztypen können null sein, Werttypen dagegen nicht.

Wertetyp im Stapel und Referenztyp im Heap

Sie können das Array mit out oder ref an die Funktion übergeben. Nur Initialisierungsmethoden sind unterschiedlich.

Mehr..

Devendra Gohel
quelle
3

Testen Sie, ob es sich um einen Referenz- oder Wertetyp handelt:

// we create a simple array of int
var a1 = new int[]{1,2,3};
// copy the array a1 to a2
var a2 = a1;
// modify the first element of a1
a1[0]=2;
// output the first element of a1 and a2
Console.WriteLine("a1:"+a1[0]); // 2
Console.WriteLine("a2:"+a2[0]); // 2
//**************************
// all the two variable point to the same array
// it's reference type!
//**************************

Sie können es online testen: https://dotnetfiddle.net/UWFP45

Marco Staffoli
quelle
2
Es wäre einfach einfacher gewesen, ein Array zu erstellen und zu versuchen, es null zuzuweisen. Die Kompilierung würde fehlschlagen, wenn es sich um einen
Werttyp handeln
Seien Sie gewarnt. Sobald C # 8 freigegeben ist, schlägt dies auch fehl, wenn Sie die Funktion nullbare Referenztypen verwenden, da nicht nullfähige Referenztypen auch null nicht akzeptieren können.
Mark A. Donohoe
2

Das Array selbst ist ein Referenztyp. Die Werte dieses Arrays sind Wert- oder Referenztypen, die vom Array-Datentyp bestimmt werden. In Ihrem Beispiel ist das Array ein Referenztyp und die Werte sind Werttypen.

Alle eindimensionalen Arrays implementieren implizit IList<T>, wobei <T>der Datentyp des Arrays ist. Sie können diese Schnittstelle stattdessen als Datentyp Ihres Methodenparameters verwenden. Sie können auch IEnumerable<T>für den Datentyp verwenden. In beiden Fällen (oder auch wenn Sie nur verwenden int[]) sollten Sie es nicht explizit als refParameter übergeben müssen.

Scott Dorman
quelle
0

// Der Verweis auf das Array wird als Wert übergeben. Dies ist die Quelle der Verwirrung :-) ...

        int[] test = { 1, 2, 3, 4 };

        modifContenuSansRef(test);
        Console.WriteLine(test[0]); // OK --> 99 le contenu du tableau est modifié

        modifTailleSansRef(test);
        Console.WriteLine(test.Length); // KO --> 4 La taille n'est pas modifiée

    }

    static void modifContenuSansRef(int[] t)
    {
        t[0] = 99;
    }

    static void modifTailleSansRef(int[] t)
    {
        Array.Resize(ref t, 8);
    }
Domi
quelle
0

Arrays sind immer Referenztypen. Es spielt keine Rolle, dass das Array einen Werttyp wie int oder einen Referenztyp wie string enthält. Wenn Sie beispielsweise ein Array deklarieren

int[] integers=new int[10];;

Die Ganzzahlvariable selbst enthält nur einen Verweis auf das Array, das sich im Heap befindet.

Es wird auch von vielen Leuten erwähnt, dass Sie den Werttyp vom Referenztyp unterscheiden können. Dies hängt nur davon ab, ob die Variable null sein kann oder nicht. Ich möchte erwähnen, dass in c # derzeit Werttypen auch null sein können

zum Beispiel

int? integer=null

und es ist keine gute Möglichkeit, den Typ als Referenz zu identifizieren, oder der Wert hängt nur davon ab, ob die Variable null sein kann oder nicht.

So_oP
quelle
-2

Nur ein kleiner Einblick:

Stellt beispielsweise inteine einzelne Ganzzahl dar, int[]repräsentiert ein Array von Ganzzahlen.

Um das Array mit bestimmten Abmessungen zu initialisieren, können Sie das newSchlüsselwort verwenden und die Größe in eckigen Klammern nach dem Typnamen angeben:

//create a new array of 32 ints.
int[] integers = new int[32];

Alle Arrays sind Referenztypen und folgen der Referenzsemantik. Daher ist das integersArray in diesem Code ein Referenztyp , obwohl die einzelnen Elemente primitive Werttypen sind. Also, wenn Sie später schreiben:

int[] copy = integers;

Dadurch wird einfach die gesamte Variablenkopie so zugewiesen, dass sie auf dasselbe Array verweist. Es wird kein neues Array erstellt.

Die Array-Syntax von C # ist flexibel. Sie können Arrays deklarieren, ohne sie zu initialisieren, damit das Array später im Programm dynamisch angepasst werden kann. Mit dieser Technik erstellen Sie im Grunde genommen eine Nullreferenz und verweisen diese Referenz später auf eine dynamisch zugewiesene Strecke von Speicherplätzen, die mit einem newSchlüsselwort angefordert werden :

int[] integers;
integers = new int[32];

Danke.

Rahul Bhat
quelle