Est-ce que int [] est un type référence ou un type valeur?

124

Je sais qu'un int est un type valeur, mais que sont les tableaux de types valeur? Types de référence? Types de valeur? Je veux passer un tableau à une fonction pour vérifier quelque chose. Dois-je simplement passer le tableau, car il passera simplement la référence de celui-ci, ou devrais-je le passer comme ref?

dévoré d'elysium
la source
11
À l'avenir, vous pouvez vérifier si quelque chose est passé par référence ou par valeur en créant une variable, en passant cette variable dans une méthode qui modifie cette variable, et en vérifiant la valeur de cette variable après son exécution dans la méthode. Si c'est le même, il est passé par valeur, différent, passé par référence.
11
@ darkassassin93: Le passage par référence ou par valeur n'a aucun rapport avec le fait que quelque chose est un type référence ou un type valeur. (Les types de valeur peuvent être passés par référence et les types de référence peuvent être passés par valeur.)
LukeH
2
Dans la plupart des cas, si vous pouvez stocker [null] dans un champ ou une variable, vous pouvez supposer qu'il s'agit d'un type ref. Les exceptions sont certainement des types Nullable (Nullable <int> ou int?) Ainsi que des chaînes.
Noel Widmer
3
@ NoëlWidmer Les chaînes ne font pas exception: ce sont des types ref.
Arthur Castro
2
@ArthurCastro Argree à 50%: les chaînes héritent de la classe, ce qui signifie qu'elles sont des types de référence. Cependant, leur égalité est basée sur l'identité (comparisme des valeurs) plutôt que sur la référence et leur comportement de réussite est remplacé pour correspondre au comportement des types valeur. Fondamentalement, ce sont des types de référence par définition mais se comportent davantage comme des types valeur par implémentation.
Noel Widmer

Réponses:

201

Les tableaux sont des mécanismes qui vous permettent de traiter plusieurs éléments comme une seule collection. Microsoft® .NET Common Language Runtime (CLR) prend en charge les tableaux unidimensionnels, les tableaux multidimensionnels et les tableaux en dents de scie (tableaux de tableaux). Tous les types de tableaux sont implicitement dérivés de System.Array, lui-même dérivé de System.Object. Cela signifie que tous les tableaux sont toujours des types de référence qui sont alloués sur le tas géré et que la variable de votre application contient une référence au tableau et non au tableau lui-même.

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

Yannick Motton
la source
54
Les types valeur héritent de System.ValueType qui lui-même hérite de System.Object. Donc, juste parce que Array dérive de System.Object ne signifie pas qu'il s'agit d'un type de référence. Ce qui fait de System.Array un type de référence, c'est que ses instances sont copiées par référence. IOW, concentrez-vous sur le fait que System.Array est une classe. C'est ce qui en fait un type de référence.
P.Brian.Mackey
8
<nitpick> Je sais qu'il peut sembler que la documentation implique que System.Array dérivant de System.Object en fait un type de référence. Bien qu'il puisse ne pas être vrai qu'un type qui dérive de System.Object soit un type de référence, la seule exception à cette règle est System.ValueType, qui est traité différemment par le compilateur. </nitpick>
Yannick Motton
Le lien ci-dessus est rompu. Voici un autre lien msdn qui montre la hiérarchie d'héritage de System.Array: msdn.microsoft.com/de-de/library/system.array(v=vs.110).aspx
MUG4N
Tout ce qui dérive de System.Object est un type de référence, sauf s'il dérive également de System.ValueType. @ P.Brian.Mackey juste parce qu'un type est une classe ne signifie pas que c'est un type de référence, car en arrière-plan, les structs ne sont que des classes qui dérivent de System.ValueType.
David Klempfner
31

Le test le plus simple pour le type de référence par rapport au type de valeur est que les types de référence peuvent l'être null, mais pas les types de valeur.

Alex Reitbort
la source
46
... sauf pour les types de valeur Nullable, qui sont Nullables (vous pouvez définir la valeur sur Null, ce qui signifie la valeur Null pour le type plutôt qu'une référence Null ) et qui sont toujours des types valeur.
Jon Skeet
1
Jamais pensé à faire cela en essayant de comprendre si ce sont des types de valeur ou non! Bonne idée.
dévoré de l'elysium
6

Tout d'abord, je veux vous dire que Array est un type de référence. Pourquoi? J'explique jeter un exemple ici.

Exemple:

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.

Les types de référence peuvent également être nuls, contrairement aux types valeur.

type de valeur stocké dans Stack et type de référence stocké dans Heap

Vous pouvez passer array pour fonctionner en utilisant out ou ref. Seules les méthodes d'initialisation sont différentes.

plus..

Devendra Gohel
la source
3

Testez pour vérifier s'il s'agit d'un type de référence ou de valeur:

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

Vous pouvez le tester en ligne: https://dotnetfiddle.net/UWFP45

Marco Staffoli
la source
2
Il aurait simplement été plus facile de créer un tableau et d'essayer de l'attribuer à null. La compilation échouerait s'il s'agissait d'un type valeur ..
dévoré l'elysium
Soyez prévenu. Une fois C # 8 publié, il échouera également si vous utilisez la fonctionnalité de types de référence Nullable car les types de référence non Nullable ne peuvent pas non plus accepter Null.
Mark A. Donohoe du
2

Le tableau lui-même est un type de référence. Les valeurs de ce tableau sont des types valeur ou référence tels que déterminés par le type de données du tableau. Dans votre exemple, le tableau est un type référence et les valeurs sont des types valeur.

Tous les tableaux à une dimension implémentent implicitement IList<T>, où <T>est le type de données du tableau. Vous pouvez utiliser cette interface comme type de données de votre paramètre de méthode à la place. Vous pouvez également utiliser IEnumerable<T>pour le type de données. Dans les deux cas (ou même si vous utilisez simplement int[]), vous ne devriez pas avoir besoin de le passer explicitement en tant que refparamètre.

Scott Dorman
la source
0

// La référence au tableau est passée par valeur. C'est la source de la confusion :-) ...

        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
la source
0

Les tableaux sont toujours des types de référence, peu importe que le tableau contienne un type de valeur comme int ou un type de référence comme string.When vous déclarez array par exemple

int[] integers=new int[10];

La variable integers elle-même ne contient que la référence au tableau qui résidera dans le tas.

De plus, de nombreuses personnes mentionnent que vous pouvez différer le type de valeur du type de référence simplement en fonction du fait que la variable peut être nulle ou non. Je voudrais mentionner que dans le c # actuellement, les types de valeur peuvent également être null

par exemple

int? integer=null

et ce n'est pas un bon moyen d'identifier le type est une référence ou la valeur dépend uniquement du fait que la variable peut être nulle ou non.

So_oP
la source
-2

Juste un aperçu:

Par exemple, intreprésente un seul entier, int[]représente un tableau d'entiers.

Pour initialiser le tableau avec des dimensions spécifiques, vous pouvez utiliser le newmot - clé, en indiquant la taille entre crochets après le nom du type:

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

Tous les tableaux sont des types de référence et suivent la sémantique de référence. Par conséquent, dans ce code, même si les éléments individuels sont des types de valeur primitifs, le integerstableau est un type de référence. Donc, si vous écrivez plus tard:

int[] copy = integers;

cela affectera simplement la totalité de la copie de la variable pour faire référence au même tableau, cela ne créera pas de nouveau tableau.

La syntaxe de tableau de C # est flexible, elle vous permet de déclarer des tableaux sans les initialiser afin que le tableau puisse être dimensionné dynamiquement plus tard dans le programme. Avec cette technique, vous créez essentiellement une référence nulle et vous pointez plus tard cette référence vers une étendue allouée dynamiquement d'emplacements de mémoire demandés avec un newmot - clé:

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

Merci.

Rahul Bhat
la source