2009-06-18 4 views
1
Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List< SaleItem>>(); 

saleItems = new List <SaleItem>(); 

saleItemNew.Add("1", saleItems); 

À ce stade, la liste du dictionnaire contient des valeurs.Valeur du dictionnaire C# effacement lorsque j'efface la liste qui lui a été assignée ... pourquoi?

saleItems.Clear(); 

Cependant, quand j'effacer la liste de la liste précédemment affecté, la valeur du dictionnaire est maintenant vide ... pourquoi?

Répondre

11

Le dictionnaire contient la même référence à la liste, donc modifier la liste changera les deux références.

documentation Microsoft sur les types de référence: http://msdn.microsoft.com/en-us/library/490f96s2.aspx

+0

Je suppose que les listes sont de la même manière? – Dano

+0

Oui, ils le sont. Toute personne qui modifie la référence le modifie pour tous ceux qui utilisent la référence. Pensez à la référence comme rien de plus qu'un pointeur vers la liste sous-jacente. – jjxtra

+0

En parlant de cela, si vous voulez ajouter beaucoup de listes qui ne partagent pas la même référence, faites simplement "new List ()" et ajoutez cela au dictionnaire chaque fois que vous avez besoin d'une nouvelle liste. – jjxtra

2

La raison est que Dictionary est une référence et non un type de valeur. Lorsque vous affectez un dictionnaire à une autre variable, il n'effectue pas de copie en profondeur. Au lieu de cela, il pointe simplement une autre référence sur le même objet. Comme il n'y a qu'un seul objet, l'effacement par l'une ou l'autre référence sera visible pour les deux références.

Ceci contrairement aux types de valeur dans le .Net Framework. L'affectation d'un type de valeur effectue essentiellement une copie superficielle des données et crée deux objets indépendants. Notez que si le type de valeur a un champ de référence, les deux champs dans les deux types de valeur pointeront toujours vers le même objet.

1

il a à voir avec l'utilisation de la mémoire et des pointeurs. Vous avez une pile, et un tas lors de l'allocation de mémoire pour les objets, cette mémoire est l'un des tas. Votre variable saleItems est définie sur la pile et pointe vers l'adresse mémoire sur le tas. Votre dictionnaire est également sur la pile pointant vers le tas.

quand vous dites:

saleItems = new List<SaleItem>() 

les saleItems variables est poussé sur la pile et contient une adresse mémoire les points à l'emplacement des données sur le tas. Disons 0x0100. Maintenant, vous ajoutez un nouveau DictionaryItem à votre dictionnaire. Le DictionaryItem est placé sur le tas avec deux propriétés, clé et valeur. Dans ce cas, vous avez ajouté saleItems comme Value, de sorte que Value a également l'adresse 0x0100. Maintenant DictionaryItem.Value pointe sur la même mémoire que saleItems. Lorsque vous appelez saleItems.Clear, vous dites trouver la liste à l'adresse 0x0100 et supprimer tous les éléments. Donc le dictionnaire et la variable deviennent vides parce qu'ils pointent sur la même mémoire. Ce que vous voulez faire est de dire saleItems = new List<SaleItem>(); encore. Maintenant, saleItems pointera vers une nouvelle adresse sur le tas (disons 0x0200). DictionaryItem.Value pointe toujours sur l'adresse mémoire 0x0100 afin que vous puissiez agir sur la variable saleItems sans affecter les données dans votre dictionnaire.

Pour plus d'informations sur des piles et des tas de C# essayer cet article: http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91

+1

Voici les détails d'implémentation. Le point saillant ici est le «type de valeur» par rapport au «type de référence», et non les détails de la façon dont ils pourraient être mis en œuvre en interne. – jason

+1

IMO - les surnoms de «type de valeur» et de «type de référence» n'ont pas de sens si vous ne comprenez pas comment la mémoire sous-jacente est utilisée, et cela nécessite de comprendre la pile et le tas et leur relation. Les classes, les délégués, etc. sont des types de référence, mais que signifie être un type de référence. Cela signifie que la mémoire de la pile est utilisée pour référencer une adresse mémoire dans le tas. Ints, bools, énumérations sont des types de valeur, mais qu'est-ce que cela signifie? Cela signifie que la mémoire est utilisée sur la pile pour stocker une valeur vraie. OMI c'est essentiel à comprendre. – NerdFury

0

Ajout de la liste dans le dictionnaire est juste une copie peu profonde ... Une nouvelle liste avec les mêmes valeurs ne sont pas créée et ajoutée (un copie profonde); plutôt une référence à l'ancienne liste est ajoutée.

0

Il utilise la même référence.

Une meilleure façon de le faire est

Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<SaleItem>>(); 
saleItemNew.Add("1", new List<SaleItem>()); 

Et pour la compensation

saleItemNew["1"] = new List<SaleItem>(); 
0

Comme il est un type de référence, juste le pointeur sur les valeurs dans la mémoire est copiée et non pas les valeurs elles-mêmes. Vous pouvez spécifier le comportement que vous voulez avec un constructeur:

De Perls dot net: // // Copiez le dictionnaire à un second objet. // Dictionnaire copy = new Dictionnaire (dictionnaire);

Questions connexes