Remove from HashSet while Looping

Hi

I need to Loop through HashSet, and when condition is met, I need to remove those particular objects from the HashSet, but ofc its getting me error that Im removing stuff from HashSet while I`m iterating over it.

I tried this, but the same error it foreach line.

HashSet<GameObject> temporaryMyObjects = myObjects; //myObjects is HashSet 
  
foreach (GameObject Object in myObjects)
{
    if (Object == player) { continue; }
  
    Vector2 distance = Object.transform.position - player.transform.position;
  
    if (distance.magnitude > 5000)
    {
        Object.SetActive(false);
        temporaryMyObjects .Remove(Object);
    }
}
myObjects= temporaryMyObjects ;

Any idea please? I think this should work, but it still says Im tryin to modify it, even if Im modifying some other hashset.

Unfortunately, HashSets are reference types. Assignment (the = operator) just makes a copy of the reference, but they still point to the same object. So you are, in fact, still iterating over the original HashSet.

I second BoredMormon’s suggestion for LINQ, as it is awesome, but it’s a slightly different paradigm.

An alternative method is to use the built-in set operators:

HashSet<GameObject> excludedObjects = new HashSet<GameObject>();
 
foreach (GameObject Object in myObjects)
{
   if (Object == player) { continue; }
 
   Vector2 distance = Object.transform.position - player.transform.position;
 
   if (distance.magnitude > 5000)
   {
       Object.SetActive(false);
       excludedObjects .Add(Object);
   }
}

//Remove all elements in the second set from the first set.
myObjects.ExceptWith(excludedObjects) ;

You can’t add or remove items from a collection while using its enumerator. This is especially true of the Dictionary and HashSet collections, which have no natural order.

Couple of options to solve

  • Use LINQ to create a new collection with desired elements removed
  • Store the elements to be removed in a separate collection. Once you have all the items, iterate over the new collection to remove them from the original.

You can’t remove elements in a foreach loop, but you can by just using a index variable like this:

for (int i = 0; i < myObjects.size; i++)
         {
             if (myObjects *== player) { continue; }*

Vector2 distance = myObjects*.transform.position - player.transform.position;*

if (distance.magnitude > 5000)
{
myObjects*.SetActive(false);*
temporaryMyObjects .Remove(myObjects*);*
}
}
Or temporarily store the current object in a variable
for (int i = 0; i < myObjects.size; i++)
{
GameObject object = myObjects*;*

if (object == player) { continue; }

Vector2 distance = object .transform.position - player.transform.position;

if (distance.magnitude > 5000)
{
object .SetActive(false);
temporaryMyObjects .Remove(object );
}
}
I have never used hashsets but it works with things like Lists, from a quick search I learned that .size get the number of elements of the hashsets so I used that as the iteration limit, dunno if it’s actually the right way.
Edit: As for “modifying some other hashset”, it seems like you are just referencing the original hashset with a new variable, but this will not create a new hashset, you are in fact directly accessing the original hashset, you just use the reference to access it.