2010-06-03 2 views
1

У меня возникла небольшая проблема с изменением элементов объекта в списке с использованием найденного индекса.C# Изменение объектов в списке

Так что это метод, который я в настоящее время работаю с:

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(); 
} 

Этот метод принимает несколько параметров, в том числе инвентаризации/список. Я проверяю, подходит ли элемент, и если да, я вижу, есть ли в списке другой элемент с тем же именем, найдите индекс и добавьте больше элемента. Однако количество добавленного предмета внезапно становится таким же, как и количество элемента в списке. По какой-то причине это также изменяет количество элемента вне списка. Поэтому, вместо количества, складывающегося следующим образом: 1, 2, 3, 4, они складываются следующим образом: 1, 2, 4, 8. Как я могу сделать так, чтобы количество добавленного элемента не изменилось?

Я только начал изучать, как использовать списки, поэтому, если есть что-то, что мне не хватает, не стесняйтесь критиковать. Заранее спасибо.

Отметить: Спасибо за самый быстрый ответ! Извините за плохое имя (myArray); это был ArrayList. CurrentAmount и maxAmount относятся к текущему весу в инвентаре и максимальному весу, который может содержать инвентарь. Кроме того, я не хочу просто добавлять 1 к количеству; Я хочу, чтобы он добавил количество предметов, в которые я проходил. Спасибо за советы. Я, вероятно, займусь использованием словаря.

+2

По теме, связанной с неродственными темами, я не понимаю, почему параметр List myArray является ref. –

+0

Я думал, что ref разрешит список, в который я прошел, чтобы быть затронутым. – kwong22

+0

В этом случае это не обязательно. Вы должны прочитать Передача Параметров в C# (http://www.yoda.arachsys.com/csharp/parameters.html). –

ответ

9

То, что здесь происходит, что myArray[id] и itemотносятся к одному объекту. List.Contains сравнивает по ссылке, а не по значению.

Так выглядит, как вы хотите, чтобы просто сделать

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

, чтобы указать, что есть еще один из этого элемента в списке.

Однако использование этого списка является принципиально неправильным подходом. Вы должны использовать словарь или набор для поиска O (1).

Если вы взяли словарный маршрут, вы бы что-то вроде:

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

Несколько других примечаний:

  • Избегайте ref arguments (если вы не знаете, что вы делаете). Нет причин, чтобы плохо названное myArray (myList было бы улучшением, но inventory было бы пятно), переданное здесь как ссылка.
  • Предпочитает properties над getXXX() методами.
  • Предпочитает классы по произвольным статическим методам. Описанный здесь метод звучит так, как будто он относится к классу Inventory, а не как некоторый статический метод, не имеющий отношения к конкретному экземпляру где-то. ref float currentAmount должен быть членом класса, а не явным параметром метода.
  • Запустите StyleCop над вашим кодом. Make it a pre-build event.Это заставит вас входить в хорошие привычки стиля C#, такие как классы и методы именования с большой буквы (и использование свойств по методам get/set тоже).
+0

Yup, словарь если вы беспокоитесь о счете и HashSet , если вы этого не сделаете. –

+0

+1 Приятно положил - мне особенно нравится руководство по именованию стандартов. Удивительно, как часто хорошие разработчики делают свою жизнь проще, в то время как начинающие или бедные разработчики (которые * нуждаются в помощи) не делают этого. –

4

Вам лучше использовать словарь, в котором вы используете имя элемента для индексации отдельных элементов.

В этом смысле, а не поиск элемента (и держать похожий на ваш, например), вы можете просто пойти

/* 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"); 
    } 
} 

Я также был бы соблазн создать свой собственный класс Inventory (который держал его собственный словарь поле), так что вы могли бы сделать метод формирования цепочки, а именно:

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

вы бы достичь этого, имея свой метод добавления возврата «этот» (т.е. типа инвентаризации не недействительными).

getQuantity будет просто «возвращать myArray [item.name] .Quantity», за исключением того, что вы не должны вызывать переменную Dictionary в классе Inventory «myArray».

0

Эти линии имеют в виду тот же пункт в списке

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

С item уже в списке, вы получаете еще одну переменную ссылаюсь на тот же объект, когда вы говорите IndexOf. Кажется, что у вас может быть ошибка в вашей логике ранее в вашей программе, потому что item всегда будет иметь такое же количество myArray[id].Quantity.

Из вашего фрагмента кода кажется, что вы хотите создать новый элемент и определить, есть ли этот тип товара уже в списке. Если это так, вы добавили бы его количество в ранее существовавший элемент этого типа.

Смежные вопросы