Search code examples
c#classinheritancemethod-chainingmethod-signature

What C# conventions are there for combining parent and child method outputs?


I'm learning C# after many moons in JavaScript land (just for some reference).

I read the C# inheritance introduction as well as when and when not to use new/override and (excuse the ignorance) am wondering if there are best practices or conventions for combining the output of parent and derived class methods that have the same signature.

An example (not whole file, just samples) from the game I'm building:

// CharController
using static TargetController;
public abstract class CharacterController : MonoBehaviour, ICharacter
{
      public virtual TargetTypes Target() {
        return TargetTypes.Character;
    }
}
// PlayerController
using static TargetController;
public class PlayerController : CharacterController, IPlayer
{
      public override TargetTypes Target()
    {
        return base.Target() | TargetTypes.Player;
    }
}
// EnemyController
using static TargetController;
public class EnemyController : CharacterController, IEnemy
{
      public override TargetTypes Target()
    {
        return base.Target() | TargetTypes.Enemy;
    }
}

The TargetType enum has flags enabled and types are set in powers of two so that values can be combined using the bitwise OR operator.

I am assuming (given my current understanding) that if I was to derive a class from, say, the EnemyController and defined an identical method that returned base.Target() | TargetTypes.Small (for example) I would get these three types when calling the derived (leaf) class Target method: Character, Enemy, Small.

Please feel free to tear me a new one (with wisdom and on good authority, please!) if this approach is just all wrong or there is some established convention for combining outputs of methods with the same signature (i.e. perhaps I should be chaining the methods somehow?).

Thanks for your time!


Solution

  • Looks fine to me. Although you should probably either rename it to GetTargetTypes() or make it a property:

    public abstract class CharacterController : MonoBehaviour, ICharacter
    {
        public virtual TargetTypes TargetTypes => TargetTypes.Character;
    }
    
    public class PlayerController : CharacterController, IPlayer
    {
        public override TargetTypes TargetTypes => base.TargetTypes | TargetTypes.Player;
    }
    

    Note: You might need to use the fully qualified name to prevent confusion between the enum name and the member name, if you give them the same name (which is a common practice.)