简体   繁体   English

C#更改列表中的对象

[英]C# Changing Objects within a List

I'm having a little problem changing members of an object in a list using a found index. 我在使用找到的索引更改列表中对象的成员时遇到了一些问题。

So this is the method I am currently working with: 所以这是我目前正在使用的方法:

static void addToInventory(ref List<baseItem> myArray, baseItem item, float maxAmount, ref float currentAmount)
{
    if (currentAmount + item.getWeight() <= maxAmount)
    {
        Console.WriteLine("item.Quantity = {0}", item.Quantity);
        if (myArray.Contains(item))
        {
            Console.WriteLine("Item ({0}) already exists", item.Name);
            int id = myArray.IndexOf(item);
            myArray[id].Quantity += item.Quantity;//Change occurs in this line, item.Quantity becomes the same as myArray[id].Quantity
        }
        else
        {
            Console.WriteLine("Adding new item ({0})", item.Name);
            myArray.Add(item);
        }
        currentAmount += item.getWeight();
    }
    else
    {
        Console.WriteLine("Inventory full");
    }
    myArray.Sort();
}

This method takes several parameters including the inventory/list. 此方法采用几个参数,包括清单/清单。 I check if the item fits in and if it does, I see if there is another item of the same name in the list, find the index, and add more of the item. 我检查该项目是否适合,如果适合,我查看列表中是否还有另一个同名项目,找到索引,并添加更多项目。 However, the quantity of the item added suddenly becomes the same as the quantity of the item in the list. 但是,突然增加的项目数量变得与列表中的项目数量相同。 For some reason, this also changes the quantity of the item outside of the list. 由于某些原因,这也会更改列表外的商品数量。 So therefore, instead of quantities adding up like this: 1, 2, 3, 4, they add up like this: 1, 2, 4, 8. How can I make it so that the quantity of the added item does not change? 因此,与其像这样累加数量:1、2、3、4,他们不这样累加累加:1、2、4、8。我如何做到这一点,以使增加的项目数量不变?

I've just started to learn how to use lists so if there is anything I'm missing, don't hesitate to criticize. 我刚刚开始学习如何使用列表,因此,如果我缺少任何内容,请随时批评。 Thanks in advance. 提前致谢。

To Mark: Thanks for the very quick reply! 标记:感谢您的快速回复! Sorry about the poor naming (myArray); 不好意思的命名(myArray); it used to be an ArrayList. 它曾经是一个ArrayList。 The currentAmount and the maxAmount refer to the current weight in the inventory and the max weight the inventory can hold respectively. currentAmount和maxAmount分别指库存中的当前重量和库存可以容纳的最大重量。 Also, I don't want to just add 1 to the quantity; 另外,我不想在数量上加1。 I want it to add the quantity of the item I pass in. Thanks for the tips. 我希望它添加所传递物品的数量。感谢您的提示。 I'll probably look into using Dictionary instead. 我可能会考虑使用Dictionary来代替。

What's happening here is that myArray[id] and item refer to the same object . 这里发生的是myArray[id]item 引用相同的对象 List.Contains compares by reference , not by value. List.Contains 按引用而不是按值进行比较。

So it looks like you want to simply do 所以看起来您只想做

if (myArray.Contains(item))
{
    item.Quantity++;
}

to indicate that there's one more of that item in the list. 表示列表中还有该项目。

However, using a list this way is a fundamentally incorrect approach. 但是,以这种方式使用列表从根本上来说是不正确的方法。 You should be using a Dictionary or a Set to achieve O(1) lookups. 您应该使用Dictionary或Set来实现O(1)查找。

If you took the dictionary route, you'd have something like: 如果您选择字典路线,则会遇到以下情况:

// a Set might be better -- I don't know what you're using this for
var myDict = new Dictionary<string, BaseItem>();
// ...
if (currentAmount + item.Weight <= maxAmount)
{
    if (myDict.ContainsKey(item.Name))
    {
        Console.WriteLine("Item already exists");
        item.Quantity++;
    }
    else
    {
        Console.WriteLine("Adding new item");
        myDict[item.Name] = item;
    }

    currentAmount += item.Weight;
}
else
{
    Console.WriteLine("Full");
}

A few other notes: 其他一些注意事项:

  • Avoid ref arguments (unless you know what you're doing). 避免使用ref参数 (除非您知道自己在做什么)。 There's no reason to have the poorly named myArray ( myList would be an improvement, but inventory would be spot-on) passed as a reference here. 这里没有理由将名称不佳的myArraymyList会有所改进,但inventory会很完善)通过作为参考。
  • Prefer properties over getXXX() methods. 优先于getXXX()方法的属性
  • Prefer classes over arbitrary static methods. 首选类优于任意静态方法。 The method you've described here sounds like it belongs to an Inventory class, not as some static method unrelated to a particular instance somewhere. 您在此处描述的方法听起来像它属于Inventory类,而不是与某个特定实例无关的静态方法。 ref float currentAmount should be a member of the class, not an explicit parameter to the method. ref float currentAmount应该是该类的成员,而不是方法的显式参数。
  • Run StyleCop over your code. 在代码上运行StyleCop Make it a pre-build event . 使其成为预构建事件 This will force you to get into good C# style habits, such as naming classes and methods with a capital letter (and using properties over get/set methods too). 这将迫使您养成良好的C#风格习惯,例如用大写字母命名类和方法(以及在get / set方法上使用属性)。

You would be better using a Dictionary in which you use the item's name to index individual items. 您最好使用字典,在字典中使用项目的名称来索引单个项目。

In that sense, rather than searching for the Item (and keeping similar to your example), you can simply go 从这种意义上讲,您不必去搜索Item(并保持与示例相似),而只需

/* Remove ref on dictionary, you're not setting myArray to something else */

static void addToInventory(Dictionary<string, baseItem> myArray, baseItem item, float maxAmount, ref float currentAmount)  
{  
    if (currentAmount + item.getWeight() <= maxAmount)  
    {  
        Console.WriteLine("item.Quantity = {0}", item.Quantity);  

        if (myArray[item.Name] == null)
            Console.WriteLine("Adding new item ({0})", item.Name); 
        else
            Console.WriteLine("Item ({0}) already exists", item.Name); 

        myArray[item.Name] = myArray[item.Name] ?? item;
        myArray[item.Name].Quantity += item.Quantity;
        currentAmount += item.getWeight();  
    }  
    else  
    {  
        Console.WriteLine("Inventory full");  
    }
}  

I'd also be tempted to create your own Inventory class (which held its own Dictionary field) so you could do method chaining ie: 我也很想创建自己的Inventory类(拥有自己的Dictionary字段),以便您可以进行方法链接,即:

Inventory i = new Inventory(maxAmount);
float currentItemCount = i.add(item).add(item).add(item).getQuantity(item);

You'd achieve this by having your add method return 'this' (ie type Inventory not void). 您可以通过使add方法返回“ this”(即,输入Inventory而不是void)来实现此目的。

getQuantity would just be 'return myArray[item.name].Quantity', except of course you shouldn't call the Dictionary variable within your Inventory class 'myArray'. getQuantity只是“返回myArray [item.name] .Quantity”,当然,您不应在库存类“ myArray”中调用Dictionary变量。

These lines are referring to the same item within the list 这些行引用列表中的同一项目

int id = myArray.IndexOf(item);
myArray[id].Quantity += item.Quantity;//Change occurs in this line, item.Quantity becomes the same as myArray[id].Quantity

Since item is already in the list you are getting another variable refering to the same object when you say IndexOf . 因为item已经在列表中,所以当您说IndexOf时,您将获得另一个变量,该变量引用同一对象。 It seems that you may have a bug in your logic earlier in your program because item will always have the same quantity of myArray[id].Quantity . 似乎您可能在程序的早期逻辑中存在错误,因为item始终具有相同数量的myArray[id].Quantity

From your code snippet it seems that you want to create a new item and determine if that type of item is already in the list. 从您的代码片段中,您似乎想创建一个新项目并确定该项目类型是否已在列表中。 If it is then you would add it's quantity to the pre-existing item of that type. 如果是,则将其数量添加到该类型的现有项目中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM