[英]Strange behavior of C# Dictionary
我有以下简化程序
using System;
using System.Collections.Generic;
using System.Text;
class ItemClass {
public int Id = 0;
public int[] Childs = new int[] { };
public int Count = 0;
}
class Class1 {
Dictionary<int, ItemClass> _Items = new Dictionary<int, ItemClass> { };
private void AddRecursive(int ItemID, int count, ref Dictionary<int, ItemClass> ItemList) {
if (!_Items.ContainsKey(ItemID)) {
return;
}
ItemClass _item = _Items[ItemID];
if (!ItemList.ContainsKey(ItemID)) {
ItemList.Add(ItemID, _item);
}
ItemList[ItemID].Count += count;
if (_item.Childs.Length > 0) {
foreach (int tmpItem in _item.Childs) {
AddRecursive(tmpItem, ItemList[ItemID].Count, ref ItemList);
}
}
}
public void Add(int item, int[] childs) {
if (!_Items.ContainsKey(item)) {
_Items.Add(item, new ItemClass() { Id = item, Childs = childs, Count = 0 });
}
}
public Dictionary<int, ItemClass> MakeList(int ItemID) {
if (!_Items.ContainsKey(ItemID)) {
return new Dictionary<int, ItemClass> { };
}
Dictionary<int, ItemClass> ItemList = new Dictionary<int, ItemClass> { };
AddRecursive(ItemID, 1, ref ItemList);
return ItemList;
}
}
class Program {
static void Main(string[] args) {
Class1 class1 = new Class1();
class1.Add(1111, new int[] { });
class1.Add(2222, new int[] { 1111 });
class1.Add(3333, new int[] { 1111, 2222 });
Dictionary<int, ItemClass> items1 = class1.MakeList(3333);
foreach (ItemClass item in items1.Values) {
Console.WriteLine(item.Id + " " + item.Count);
}
Console.WriteLine("");
Dictionary<int, ItemClass> items2 = class1.MakeList(3333);
foreach (ItemClass item in items2.Values) {
Console.WriteLine(item.Id + " " + item.Count);
}
Console.ReadKey();
}
}
它具有一项简单的任务,即对项目进行计数并显示项目列表及其计数。 当我第一次调用MakeList
函数时,可以预期结果。
预期:
3333 1
1111 2
2222 1
3333 1
1111 2
2222 1
实际
3333 1
1111 2
2222 1
3333 2
1111 7
2222 3
当我重新声明变量ItemList
,我期望第二次调用该函数时看到相同的结果,但是就像先前调用的结果被缓存并重新使用一样。
为什么会这样,为什么会这样? 有什么办法可以避免呢?
您重新声明ItemList
,但使用内部_Items
相同对象: ItemClass _item = _Items[ItemID];
并增加对同一对象的计数。 这就是为什么part :)。 避免部分可能是创建新项目。
其实没有什么奇怪的。 您刚刚在调用AddRecursive
方法时修改了ItemClass
对象中Count
属性的值。
假设您确实想要获得期望的结果,则只需要深度克隆ItemClass
对象或简单地创建新实例并复制属性的原始值即可。
ItemClass _item = new ItemClass() { Childs = _Items[ItemID].Childs, Count = _Items[ItemID].Count, Id = _Items[ItemID].Id };
代替这个
Itemclass _item = _Items[ItemId]
您的问题是您在运行AddRecursive
_Items
词典中ItemClass
实例的Count
属性。
摆脱那个可变的Count
属性(它实际上不应该在ItemClass
),并将代码简化为
class ItemClass
{
public int Id = 0;
public int[] Childs = new int[] { };
}
class Class1
{
Dictionary<int, ItemClass> _Items = new Dictionary<int, ItemClass>();
private void AddRecursive(int itemId, Dictionary<int, int> itemList)
{
if (!_Items.ContainsKey(itemId))
return;
if (!itemList.ContainsKey(itemId))
itemList.Add(itemId, 1);
else
itemList[itemId] += 1;
var item = _Items[itemId];
if (item.Childs.Length > 0)
foreach (int tmpItem in item.Childs)
AddRecursive(tmpItem, itemList);
}
public void Add(int item, int[] childs)
{
if (!_Items.ContainsKey(item))
_Items.Add(item, new ItemClass() { Id = item, Childs = childs });
}
public Dictionary<int, int> MakeList(int itemId)
{
if (!_Items.ContainsKey(itemId))
return new Dictionary<int, int>();
var itemList = new Dictionary<int, int>();
AddRecursive(itemId, itemList);
return itemList;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.