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

How to Avoid Updating item searched by Dictionary?

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

    // 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;
    }

为了从另一个 class 的 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;

上面发生的事情是,我搜索了一个项目并得到它“refScannedItem”,然后我将其描述附加到 "BOX of " + boxItem.Quantity + " " + refScannedItem.Description; 。因此,如果原始描述是 "Aquafina",我将其设为 "BOXof 10 Aquafina"。上次我扫描同一个产品,我找到了这个产品,但是现在它的描述变成了"Box of 10 Aquafina",所以我的设置描述行变成了"BOX of 10 BOX of 10 Aquafina"。 "BOX of 10 BOX of 10 BOX of 10 Aquafina" 等也是如此。

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

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

请针对上述问题提出解决方案。非常感谢任何帮助。

谢谢

这应该可以解决问题:

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

您正在从字典中获取一个对象 - 然后对其进行更改,因此它的属性当然也会在字典中更改...您还没有克隆它,所以为什么要复制一份?

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

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

看起来您需要复制 RefItemDetails 以便在您从对 UtilityLibrary.FindRefItem(boxItem.UnitBarcode.Trim())

的调用中取回它之后进行修改

您 return 指向包含在您的 Dictionary 中的项目的指针,因此您对该对象所做的任何操作都将存储在原始 Dictionary 对象中是有意义的。

您想要做的是,在 FindRefItem 中,return指向 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 new RefItemDetails(itemDet);

替换return itemDet;

我认为你的做法是错误的。

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

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

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

或类似的东西。