[c#] C# Remove object from list of objects

I have a list of objects and I am trying to remove a specific object in the list by first checking a property in the object.

Originally I used a foreach but then realised you can't use this while modifying a collection, so I decided to use a normal for but then I'm not sure how to write code that does what I originally wrote.

How do I go about writing code to do what I originally had?

Thanks

Here's my code:

    public void DeleteChunk(int ChunkID)
    {
        //foreach (Chunk i in ChunkList)
        //{
        //    if (i.UniqueID == ChunkID)
        //    {
        //        ChunkList.Remove(i);
        //    }
        //}

        //This won't work because here i is just an integer so i.UniqueID won't exist.
        for (int i = 0; i < ChunkList.Capacity; i++)
        {
            if (i.UniqueID == ChunkID)
            {
                ChunkList.Remove(i);
            }
        }

    }

This question is related to c#

The answer is


First you have to find out the object in the list. Then you can remove from the list.

       var item = myList.Find(x=>x.ItemName == obj.ItemName);
       myList.Remove(item);

There are two problems with this code:

  • Capacity represents the number of items the list can contain before resizing is required, not the actual count; you need to use Count instead, and
  • When you remove from the list, you should go backwards, otherwise you could skip the second item when two identical items are next to each other.

If ChunkList is List<Chunk>, you can use the RemoveAll method:

ChunkList.RemoveAll(chunk => chunk.UniqueID == ChunkID);

You're removing and then incrementing, which means you'll be one ahead of yourself. Instead, remove in reverse so you never mess up your next item.

for (int i = ChunkList.Count-1; i >=0; i--)
{
    if (ChunkList[i].UniqueID == ChunkID)
    {
        ChunkList.RemoveAt(i);
    }
}

You can simplify this with linq:

var item = ChunkList.SingleOrDefault(x => x.UniqueId == ChunkID);
if (item != null)
    ChunkList.Remove(item);

You can also do the following, which will also work if there is more than one match:

ChunkList.RemoveAll(x => x.UniqueId == ChunkID);

Firstly, you are using Capacity instead of Count.

Secondly, if you only need to delete one item, then you can happily use a loop. You just need to ensure that you break out of the loop after deleting an item, like so:

int target = 4;

for (int i = 0; i < list.Count; ++i)
{
    if (list[i].UniqueID == target)
    {
        list.RemoveAt(i);
        break;
    }
}

If you want to remove all items from the list that match an ID, it becomes even easier because you can use List<T>.RemoveAll(Predicate<T> match)

int target = 4;

list.RemoveAll(element => element.UniqueID == target);

You can use a while loop to delete item/items matching ChunkID. Here is my suggestion:

public void DeleteChunk(int ChunkID)
{
   int i = 0;
   while (i < ChunkList.Count) 
   {
      Chunk currentChunk = ChunkList[i];
      if (currentChunk.UniqueID == ChunkID) {
         ChunkList.RemoveAt(i);
      }
      else {
        i++;
      }
   }
}

Originally I used a foreach but then realised you can't use this while modifying a collection

You can create a copy of the collection and iterate over that using ToList() to create to copy:

 foreach(Chunk chunk in ChunkList.ToList())
 {
     if (chunk.UniqueID == ChunkID)
     {
         ChunkList.Remove(chunk);
     }
 }

You're checking i's UniqueID while i is actually an integer. You should do something like that, if you want to stay with a for loop.

for (int i = 0; i < ChunkList.Capacity; i++)
{
    if (ChunkList[i].UniqueID == ChunkID)
    {
        ChunkList.Remove(i);
    }
}

You can, and should, however, use linq:

ChunkList.Remove(x => x.UniqueID == ChunkID);

One technique is to create a copy of the collection you want to modify, change the copy as needed, then replace the original collection with the copy at the end.


Simplest solution without using LINQ:

    Chunk toRemove = null;
    foreach (Chunk i in ChunkList)
    {
        if (i.UniqueID == ChunkID)
        {
            toRemove = i;
            break;
        }
    }
    if (toRemove != null) {
        ChunkList.Remove(toRemove);
    }

(If Chunk is a struct, then you can use Nullable<Chunk> to achieve this.)