Int [] è un tipo di riferimento o un tipo di valore?


124

So che un int è un tipo di valore, ma quali sono le matrici di tipi di valore? Tipi di riferimento? Tipi di valore? Voglio passare un array a una funzione per verificare qualcosa. Devo solo passare l'array, poiché passerà solo il riferimento di esso, o dovrei passarlo come ref?


11
In futuro, puoi verificare se qualcosa viene passato per riferimento o per valore creando una variabile, passando quella variabile in un metodo che modifica quella variabile e controllando quale sia il valore di quella variabile dopo che è stato eseguito attraverso il metodo. Se è lo stesso, viene passato per valore, diverso, passato per riferimento.

11
@ darkassassin93: il passaggio per riferimento o per valore non è correlato al fatto che qualcosa sia un tipo di riferimento o un tipo di valore. (I tipi di valore possono essere passati per riferimento e i tipi di riferimento possono essere passati per valore.)
LukeH

2
Nella maggior parte dei casi, se è possibile memorizzare [null] all'interno di un campo o di una variabile, si può presumere che sia un tipo di riferimento. Le eccezioni sono certamente tipi nulli (Nullable <int> o int?) E stringhe.
Noel Widmer,

3
@ NoëlWidmer Le stringhe non fanno eccezione: sono tipi di riferimento.
Arthur Castro,

2
@ArthurCastro Argree al 50%: le stringhe ereditano dalla classe, il che significa che sono tipi di riferimento. Tuttavia, la loro uguaglianza si basa sull'identità (confronto di valori) piuttosto che sul riferimento e il loro comportamento di passaggio viene ignorato per corrispondere al comportamento dei tipi di valore. Fondamentalmente sono tipi di riferimento per definizione ma si comportano più come tipi di valore per implementazione.
Noel Widmer,

Risposte:


201

Le matrici sono meccanismi che consentono di trattare diversi elementi come un'unica raccolta. Il Common Language Runtime (CLR) di Microsoft® .NET supporta matrici monodimensionali, matrici multidimensionali e matrici frastagliate (matrici di matrici). Tutti i tipi di array derivano implicitamente da System.Array, che a sua volta deriva da System.Object. Ciò significa che tutti gli array sono sempre tipi di riferimento allocati sull'heap gestito e la variabile dell'app contiene un riferimento all'array e non all'array stesso.

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


54
I tipi di valore ereditano da System.ValueType che eredita da System.Object. Quindi, solo perché Array deriva da System.Object non significa che sia un tipo di riferimento. Ciò che rende System.Array un tipo di riferimento è che le sue istanze vengono copiate per riferimento. IOW, concentrati sul fatto che System.Array è una classe. Questo è ciò che lo rende un tipo di riferimento.
P.Brian.Mackey,

8
<nitpick> So che potrebbe sembrare che la documentazione implichi che System.Array derivante da System.Object lo rende un tipo di riferimento. Anche se può non essere vero che qualsiasi tipo derivante da System.Object sia un tipo di riferimento, l'unica eccezione a questa regola è System.ValueType, che viene trattato in modo diverso dal compilatore. </nitpick>
Yannick Motton

Il link sopra è rotto. Ecco un altro link MSDN che mostra la gerarchia di ereditarietà di System.Array: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N

Tutto ciò che deriva da System.Object è un tipo di riferimento, A MENO CHE deriva anche da System.ValueType. @ P.Brian.Mackey solo perché un tipo è una classe non significa che sia un tipo di riferimento, perché dietro le quinte le strutture sono solo classi che derivano da System.ValueType.
David Klempfner,

31

Il test più semplice per il tipo di riferimento rispetto al tipo di valore è che i tipi di riferimento possono essere null, ma i tipi di valore no.


46
... ad eccezione dei tipi di valore nullable, che sono nullable (è possibile impostare il valore su null, che significa il valore null per il tipo anziché un riferimento null ) e sono comunque tipi di valore.
Jon Skeet,

1
Non ho mai pensato di farlo quando provo a capire se sono tipi di valore o no! Grande idea.
divorò l'elisio il


6

Innanzitutto voglio dirti che l'array è un tipo di riferimento. Perché? Spiego un esempio qui.

Esempio:

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.

Anche i tipi di riferimento possono essere nulli, mentre i tipi di valore no.

tipo di valore archiviato in Stack e tipo di riferimento archiviato in Heap

È possibile passare la matrice per funzionare usando out o ref. Solo i metodi di inizializzazione sono diversi.

Di Più..


3

Test per verificare se si tratta di un tipo di riferimento o valore:

// 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!
//**************************

Puoi provarlo online: https://dotnetfiddle.net/UWFP45


2
Sarebbe stato più semplice creare un array e tentare di assegnarlo a null. La compilazione fallirebbe se fosse un tipo di valore ...
divorò l'elisio il

Attenzione. Una volta rilasciato C # 8, fallirà anche se stai usando la funzione dei tipi di riferimento nullable poiché i tipi di riferimento non nullable non possono accettare nulla.
Mark A. Donohoe,

2

L'array stesso è un tipo di riferimento. I valori di quell'array sono tipi di valore o di riferimento determinati dal tipo di dati dell'array. Nel tuo esempio, l'array è un tipo di riferimento e i valori sono tipi di valore.

Tutti gli array a dimensione singola implementano implicitamente IList<T>, dove si <T>trova il tipo di dati dell'array. È invece possibile utilizzare tale interfaccia come tipo di dati del parametro del metodo. È inoltre possibile utilizzare IEnumerable<T>per il tipo di dati. In entrambi i casi (o anche solo se lo usi int[]) non dovresti aver bisogno di passarlo esplicitamente come refparametro.


0

// Il riferimento all'array viene passato per valore. Questa è la fonte della confusione :-) ...

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

0

Le matrici sono sempre tipi di riferimento. Non importa che la matrice contenga un tipo di valore come int o un tipo di riferimento come stringa. Quando si dichiara una matrice per esempio

int[] integers=new int[10];

la variabile integer stessa contiene solo riferimenti all'array che risiederà nell'heap.

Inoltre, molte persone affermano che è possibile che il tipo di valore differisca dal tipo di riferimento solo in base al fatto che la variabile potrebbe essere nulla o meno. Vorrei menzionare che nel c # attualmente i tipi di valore possono anche essere nulli

per esempio

int? integer=null

e non è un buon modo per identificare il tipo è riferimento o il valore dipende solo dal fatto che la variabile potrebbe essere nulla o meno.


-2

Solo un po 'di intuizione:

Ad esempio, intrappresenta un singolo numero intero, int[]rappresenta un array di numeri interi.

Per inizializzare l'array con dimensioni specifiche, è possibile utilizzare la newparola chiave, specificando la dimensione tra parentesi quadre dopo il nome del tipo:

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

Tutti gli array sono tipi di riferimento e seguono la semantica di riferimento. Quindi, in questo codice, anche se i singoli elementi sono tipi di valore primitivi, l' integersarray è un tipo di riferimento. Quindi se in seguito scrivi:

int[] copy = integers;

questo assegnerà semplicemente l'intera copia della variabile per fare riferimento allo stesso array, non creerà un nuovo array.

La sintassi dell'array di C # è flessibile, consente di dichiarare array senza inizializzarli in modo che l'array possa essere dimensionato dinamicamente in un secondo momento nel programma. Con questa tecnica, stai fondamentalmente creando un riferimento null e successivamente puntando quel riferimento su un tratto allocato dinamicamente di posizioni di memoria richieste con una newparola chiave:

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

Grazie.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.