avoid null when multiple classes are modifying the same thing

pardon me for my question line, i couldn’t phase it better, if you know a better way to describe this problem, please let me know.


I am trying to simply my code here so i do not have to paste my thousands of lines of crap to you.

lets say I have three classes, some pseudo code here:

class A : monobehaviour{
  Dictionary<Item, int> myDict;

  void Update(){

  	foreach(var pair in myDict){
  		//do something with the pair.key  and pair.value
  	}
  }
}

class B : monobehaviour{
	List<Item> myList;

	void Update(){
		foreach(var i in myList){
			//do something with i
		}
	}

}

class Item : monobehaviour{

	List<Item> neighbors;

	void Update(){

		for(int i=0;i<neighbors.Count;i++){
			if( /* me and my neighbor is too close */)
			{
				Destroy(neighbor);
			}
		}

	}

}

as you can see, sometimes Item class would destroy other Item if certain condition is met, this will cause other classes to complain since some pair’s key in class A 's myDict or the certain Item in myList from class B might be null.


right now i use a for loop to check if there is any item in the list/dict is null, and remove them before the list/dict is being used.

But i feel like this is dirty and hard to manage. This approach is guaranteed to work tho.


there are other two options in my mind but with this production project being exhibited right now i do not want to experiment too much.

  1. use a System.Action / Event , call it right after any Destroy() function is called. and other classes can listen to it and clean up their lists/dict/whatever

  2. use lock to prevent list being modified when it is being iterated over.


if you can point out the pros and cons of the three approaches, i would be very grateful.

I think MonoBehavior has a OnDestroyed event. You could register to this event in Start or Awake of class A and any time you add to the dictionary. Then in your event handler, simply unregister from the event and remove the item from the dictionary.

@Iarus has a good answer to the question.


You can extend it out a little further. When the item is added to the list on ‘A’, you can add a MonoBehaviour that can be used to de-register the object should it ever be destroyed.


class NotifyOnDestruction : monobehaviour{
     A ReferencedFrom;
 
   void OnDestroy()
   {
       if (ReferencedFrom != null) ReferencedFrom.RemoveFromList(gameObject);
   }
 }

This means that A gets called every time that an item in its list gets deleted.


When adding items to the list in A, you’ll need the following…

Item.AddComponent<NotifyOnDestruction>().ReferencedFrom = this;