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

saleItems = new List <SaleItem>(); 

saleItemNew.Add("1", saleItems); 

此时,词典中的列表具有值。当我清除先前分配给它的C#字典值清除。为什么?

saleItems.Clear(); 

然而,当我清除掉以前分配给它的列表中,字典的值列表现在是空的......为什么?

回答

11

该字典包含与该列表相同的参考,因此修改该列表将更改这两个参考。

有关引用类型微软文档:http://msdn.microsoft.com/en-us/library/490f96s2.aspx

+0

我假设列表是相同的方式? – Dano 2009-06-18 20:57:22

+0

是的,他们是。任何修改引用的人都会修改引用的每个人。将引用看作仅仅是指向基础列表的指针。 – jjxtra 2009-06-18 21:01:53

2

原因是Dictionary是一个引用而不是值类型。当您将字典分配给其他变量时,它不会执行深层复制。相反,它只是在同一个对象上指出另一个参考。由于只有一个对象,因此两个引用都可以通过任一引用进行清除。

这与.Net Framework中的值类型形成对比。赋值类型本质上是执行数据的浅层副本并创建两个独立的对象。请注意,如果值类型具有引用字段,则两个值类型中的两个字段仍将指向同一对象。

1

它与内存使用和指针做。分配内存给对象时,你有一个堆栈和一个堆,内存就是堆。您的saleItems变量在堆栈中定义并指向堆上的内存地址。你的字典也在栈上指向堆。

当你说:

saleItems = new List<SaleItem>() 

可变saleItems被压入堆栈,并包含一个存储器地址指向堆上的数据的位置。可以说0x0100。现在你在字典里添加一个新的DictionaryItemDictionaryItem放置在具有两个属性Key和Value的堆上。在这种情况下,您添加了saleItems作为Value,因此Value的地址也是0x0100。现在DictionaryItem.Value指向与saleItems相同的内存。当您致电saleItems.Clear时,您的意思是找到地址0x0100的列表并删除所有项目。所以字典和变量都是空的,因为它们指向相同的内存。你想要做的是再次说saleItems = new List<SaleItem>();。现在saleItems将指向堆上的新地址(如0x0200)。 DictionaryItem.Value仍然指向内存地址0x0100,因此您可以在saleItems变量上执行操作,而不会影响字典中的数据。

有关在C#栈和堆更多信息,尝试这篇文章:http://www.c-sharpcorner.com/UploadFile/rmcochran/csharp_memory01122006130034PM/csharp_memory.aspx?ArticleID=9adb0e3c-b3f6-40b5-98b5-413b6d348b91

0

添加清单只是不创建一个浅表副本......一个新的列表具有相同的价值观和添加的字典(一深拷贝);而是添加了对旧列表的引用。

0

它使用相同的参考。

一个更好的办法来做到这一点是

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

和清除

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

由于它是一个引用类型,只是指针的值在内存中被复制而不是值本身。 里,可以指定你想要构造的行为:

从点网皮尔斯: // // 复制字典的第二个对象。 // Dictionary copy = new Dictionary(dictionary);