'How to iterate through groups of modules and call a function if they inherit an interface in a generic and performant way?

I am making a modular system in C#. Modules are divided by groups and are all managed by a command object.

Right now I am writing the same code over and over because I can't find a good way to generalise it in a way that wouldn't cause performance to drop. This structure is used in a game and called every frame.

I would like modules to inherit the interfaces they are interested in. Most of my interfaces for the modules have a single function.

For example I have a IModuleCanUse, IModuleUse and IModuleGetState, interface (I have many more) This is what it looks like now:

(The example below is simplified but should get the point across)

public bool CanUse(){
   for (int i = 0; i < m_AllModuleGroups.Count; i++) {
      var moduleGroup = m_AllModuleGroups[i];
      for (int j = 0; j < moduleGroup.Modules.Count; j++) {
          var module = moduleGroup.Modules[j];
          if (!module.IsActive || !(module is IModuleCanUse moduleT)) { continue; }
          var canuse = moduleT.CanUse();
          if(canUse == false){
              return false;
          }
      } 
   }
   return true;
}

public void Use(){
   for (int i = 0; i < m_AllModuleGroups.Count; i++) {
      var moduleGroup = m_AllModuleGroups[i];
      for (int j = 0; j < moduleGroup.Modules.Count; j++) {
          var module = moduleGroup.Modules[j];
          if (!module.IsActive || !(module is IModuleUse moduleT)) { continue; }
          moduleT.Use();
      } 
   }
}

public ModuleState GetState(){
   var state = ModuleState.NoState;
   for (int i = 0; i < m_AllModuleGroups.Count; i++) {
      var moduleGroup = m_AllModuleGroups[i];
      for (int j = 0; j < moduleGroup.Modules.Count; j++) {
          var module = moduleGroup.Modules[j];
          if (!module.IsActive || !(module is IModuleGetState moduleT)) { continue; }
          state = moduleT.GetState(state);
      } 
   }
   return state
}

As you can see I am repeating the same 5 first lines of code. Iterating through the modules and checking if it is active and inherits the interface.

Is there a way to create an IEnumerator, or function that wouldn't cause garbage allocation or performance degradation and that could allow me to write this in less lines of code?

The order in which the modules are iterated through matters, and it can change at runtime, so caching the modules that inherit a certain interface in seperate lists isn't really a good option.

My main concern is if I do this with all interfaces, and then I decide to refactor the condition to call functions on modules, I'll have to go through all of them, and I might forget one which could cause bugs.

Something like this is the closest thing I can think of for a generic approach. But I am assuming this creates garbage when the action parameter is created with a lambda function

´´´

public void GenericModuleAction<T>(Action<T> action)
        {
            for (int i = 0; i < m_AllModuleGroups.Count; i++) {
                var moduleGroup = m_AllModuleGroups[i];
                for (int j = 0; j < moduleGroup.EnabledBaseModules.Count; j++) {
                    var module = moduleGroup.EnabledBaseModules[j];
                    if (!module.IsActive || !(module is T moduleT)) { continue; }
action(moduleT);
                } 
            }
        }
                    
public void Use(){
   GenericModuleAction<IModuleUse>(module => module.Use());
}

´´´

Thank you for your time.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source