如何避免更新字典搜索的项目?

时间:2015-04-21 12:56:12

标签: c# dictionary updates containskey trygetvalue

在.NET Winfroms C#app中,我有一个名为listItems的Dictionary集合。我在应用程序启动时将数据存储在其中。在静态类中,我有如下:

    // listItems is populated bt reading a file. 
    // No other operations are performed on it, except finding an item.
    public static Dictionary<string, RefItemDetails> itemsList;

   // Find RefItemDetails of barcode
    public static RefItemDetails FindRefItem(string barcode)
    {
        RefItemDetails itemDet = null;
        try
        {
            //if (itemsList.TryGetValue(barcode, out itemDet) == false)
            //    System.Diagnostics.Debug.WriteLine("Barcode " + barcode + " not found in Items");

            //itemDet = itemsList.First(item => item.Key == barcode);//.First(item => item.Barcode == barcode);

            if (itemsList.ContainsKey(barcode) ) 
                itemDet = itemsList[barcode];
        }
        catch (Exception)
        {
            itemDet = null;
        }

        return itemDet;
    }

为了从另一个类的listItems中检索项目,我使用:

    refScannedItem = null;
    // Get Unit Barcode & Search RefItem of it
    refScannedItem = UtilityLibrary.FindRefItem(boxItem.UnitBarcode.Trim());

     // Display BOX item details 
     refScannedItem.Barcode = boxItem.BoxBarcode.Trim();
     refScannedItem.Description = "BOX of " + boxItem.Quantity + " " + refScannedItem.Description;
     refScannedItem.Retail *= boxItem.Quantity;
     refScannedItem.CurrentCost *= boxItem.Quantity;

上面发生的是,我搜索一个项目&amp;我得到它“refScannedItem”,然后按"BOX of " + boxItem.Quantity + " " + refScannedItem.Description;追加它的描述。因此,如果原始描述是“Aquafina”,我将它变为“BOXof 10 Aquafina”。嵌套时间我扫描相同的产品,我找到了产品,但现在它的描述已经变成了“10盒Aquafina”,所以我的设置描述变成了“10个Aquafina的10个BOX的盒子”。像“10 Aquafina 10 BOX 10 BOX BOX”等等也是如此。

正如你在我的查找代码中看到的那样,我最初使用TryGetValue,然后尝试使用LINQ,然后尝试使用ContainsKey,但在所有这些代码中,为什么值listItem得到更新。

我理解,由于TryGetValue具有out参数,因此该值将作为reference传递,然后它将被切换。但是在listItems[key]中也会更新它!我怎样才能避免这种情况发生?我选择了Dictionary收藏以方便和放心快速搜索,但这部分给我的应用程序带来了很多问题和一个大错误。我无法找到接收值但不应更新的nay解决方案。所有文章都展示了如何搜索&amp;更新它。

请建议上述解决方案。任何帮助都非常感谢。

由于

5 个答案:

答案 0 :(得分:1)

您返回指向词典中包含的项目的指针,因此您对此Object所做的任何操作都将存储在原始Dictionary对象中。

你想要做的是,在FindRefItem中,返回一个指向你的RefItemDetails对象副本的指针。

一种简单的方法是编写一个新的构造函数。 类似的东西:

public RefItemDetails(RefItemDetails original)
{
   this.Barcode = original.Barcode ;
   this.Description = original.Description ;
   this.Retail = original.Retail ;
   this.CurrentCost = original.CurrentCost ;
   //Set any other properties here
}

然后将return itemDet;替换为return new RefItemDetails(itemDet);

答案 1 :(得分:1)

我认为你这样做是错误的。

您不应该有可写的Description属性,只要数量发生变化,您就会更新。

相反,我认为你应该有一个单独的Name属性,其中包含项目的名称(例如Aquafina)和动态创建的只读Description属性,如下所示:

public string Description
{
    get
    {
        return string.Format("Box of {0} {1}", Quantity, Name);
    }
}

或类似的东西。

答案 2 :(得分:0)

这应该可以解决问题:

if (!refScannedItem.Description.StartsWith("BOX of "))
{
    refScannedItem.Description = "BOX of " + boxItem.Quantity + " " + refScannedItem.Description;
}

答案 3 :(得分:0)

你从字典中获取一个对象 - 然后改变它,所以当然它的属性也会在字典中改变......你还没有克隆它,所以你为什么要服用它副本?

解决方案非常简单 not 来更改项目的值并以不同的方式使用修改后的文本:

var amendedDescription = "BOX of " + boxItem.Quantity + " " + refScannedItem.Description;

答案 4 :(得分:0)

看起来您需要制作RefItemDetails的副本,以便在从UtilityLibrary.FindRefItem(boxItem.UnitBarcode.Trim())

的电话中取回后进行修改