当我清除先前分配给它的列表时,C#字典值清除....为什么?

时间:2009-06-18 19:57:09

标签: c# dictionary

Dictionary <string, List <SaleItem>> saleItemNew = new Dictionary<string, List<    SaleItem>> ();

saleItems = new List <SaleItem> ();

saleItemNew.Add("1", saleItems);

此时,词典中的列表具有值。

saleItems.Clear();

但是,当我清除之前分配给它的列表时,字典的值列表现在为空......为什么?

6 个答案:

答案 0 :(得分:11)

字典包含对列表的相同引用,因此修改列表将更改两个引用。

有关参考类型的Microsoft文档:http://msdn.microsoft.com/en-us/library/490f96s2.aspx

答案 1 :(得分:1)

原因是Dictionary是引用而不是值类型。将Dictionary分配给另一个变量时,它不会执行深层复制。相反,它只是指向同一对象的另一个引用。由于只有一个对象,因此两个引用都可以看到通过任一引用清除。

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

答案 2 :(得分:0)

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

当你说:

saleItems = new List<SaleItem>()

变量saleItems被压入堆栈并包含一个内存地址,指向堆上数据的位置。让我们说0x0100。现在,您将新的DictionaryItem添加到字典中。 DictionaryItem放在堆上,具有两个属性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

答案 3 :(得分:0)

将列表添加到字典只是一个浅层副本...不会创建和添加具有相同值的新列表(深层副本);而是添加了对旧列表的引用。

答案 4 :(得分:0)

它使用相同的参考。

更好的方法是

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

清算

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

答案 5 :(得分:0)

因为它是一个引用类型,所以只复制指向内存中值的指针而不是值本身。  您可以使用构造函数指定所需的行为:

来自dot net perls:     //     //将Dictionary复制到第二个对象。     //     字典副本=新词典(字典);