Question

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?

Was it helpful?

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 ....

OTHER TIPS

The simple option would be to change the signature of ICommandEntities:

public interface ICommandEntities
{
    void Update<TId>(Entity<TId> entity)
}

This effectively gives the same constraint that you're after.

As stated in the comments, you should just make the parameter type BaseClass<T>

class Program
{
    static void Main( string[] args )
    {
        ITest x = new TestClass();

        Console.WriteLine( x.GetTypeArgTypeFrom( new BaseClass<int>() ) );

        Console.ReadKey();

    }
}

public class BaseClass<T>
{
    public Type GetTypeArgType()
    {
        return typeof( T );
    }
}

public interface ITest
{
    Type GetTypeArgTypeFrom<T>( BaseClass<T> bct );
}

public class TestClass : ITest
{
    public Type GetTypeArgTypeFrom<T>( BaseClass<T> bct )
    {
        return bct.GetTypeArgType();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top