Search code examples
c#genericsmethodsgeneric-type-parameters

How do I correctly constrain to related class type when using a generic method?


I have two base classes BaseObject and BaseObjectSettings. The first defines the object behaviour and the second defines the state of the class (useful for serialisation).

If I want to create a derived BaseObject class with specific settings then I can use a method with a generic type constraint.

public void CreateBaseObjectInstance<T>(BaseObjectSettings baseObjectSettings) where T : BaseObject
{
    var instance = pool.GetInstance<T>();
    instance.Settings = baseObjectSettings;
    scene.Add(instance);
}

The problem I am facing is that while I can constrain the generic type to BaseClass I can't constrain the BaseClassSettings to the relevant derived BaseClass. This means that I can do things like

CreateBaseObjectInstance<Banana>(new AppleSettings());

which seems a bit terrible.

What are my options given that I am currently constrained to both creating and initialising the object in the same method before adding it to the scene?


Solution

  • One way is to have all your settings classes inherit from a generic base class. The generic base class could then inherit from BaseObjectSettings. The generic type parameter indicates what kind of object this settings class is for.

    For example, for your AppleSettings,

    class AppleSettings: ObjectSettings<Apple> {
        ...
    }
    
    abstract class ObjectSettings<T>: BaseObjectSettings where T: BaseObject {}
    

    Now, you can change CreateBaseObjectInstance to accept an instance of ObjectSettings<T> instead:

    public void CreateBaseObjectInstance<T>(ObjectSettings<T> objectSettings) where T : BaseObject
    {
        var instance = pool.GetInstance<T>();
        instance.Settings = objectSettings;
        scene.Add(instance);
    }
    

    If you pass Banana as T, it would expect ObjectSettings<Banana>, preventing you from giving it AppleSettings, which is ObjectSettings<Apple>.