[英]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.