Search code examples
c#genericstype-constraints

How to add a C# generic type constraint on another generic base class?


I've read the MSDN documentation on C# generic type parameter constraints several times, but I cannot figure out how to do this, or determine if it's even possible.

Say I have a generic base class like this:

public abstract class Entity<TId> { ... }

This abstract base class does not have any type constraints, TId can be anything -- a struct, class, etc.

Now say I have a generic interface method, and I want to constrain the generic types on the method to the above class:

public interface ICommandEntities
{
    void Update<TEntity>(TEntity entity) where TEntity : ?????;
}

I can get this to compile:

public interface ICommandEntities
{
    void Update<TEntity, TId>(TEntity entity) where TEntity: Entity<TId>
}

...however then I need to explicitly add both T1 ant T2 generic args when executing the method:

commander.Update<AbcEntity, string>(abcEntity);

If possible, I would like to make the compiler infer everything, so that I can execute the method like this:

commander.Update(abcEntity);

Is this event possible? So far the only way I can get it to work is by adding an empty, non-generic base class above the generic base class and using it as a type constraint on the method:

public abstract Entity {}

public abstract EntityWithId<TId> : Entity { ... }

public interface ICommandEntities
{
    void Update<TEntity>(TEntity entity) where TEntity : Entity;
}

commander.Update(abcEntity);

... but then I end up with a pretty useless class that acts as a marker interface. Is that the only way to get away with this type of generic class & interface method design? Or am I missing something here?


Solution

  • After checking that it compiles, I will upgrade it to an answer.

    From your question and comments, you want the parameter to be Entity<Something>. You do not need to use the parametrized types directly as a type, it can be use to parametrize a parameter.

    So just do

     public void Update(Entity<T1> entity) where ....