简体   繁体   中英

How to declare a generic constraint that is a generic type

I have a two generic abstract types: Entity and Association .

Let's say Entity looks like this:

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

and Association looks like this:

public class Association<TEntity, TEntity2>
{
//...
}

How do I constrain Association so they can be of any Entity?

I can accomplish it by the following:

public class Association<TEntity, TId, TEntity2, TId2>
     where TEntity : Entity<TId>
     where TEntity2: Entity<TId2>
{
//...
}

This gets very tedious as more types derive from Association , because I have to keep passing down TId and TId2. Is there a simpler way to do this, besides just removing the constraint?

This problem is usually solved by having your generic class ( Entity<TId> , in this case) inherit from a common non-generic class.

public abstract class EntityBase
{

}

public class Entity<TId> : EntityBase
{

}

This will allow you to do:

public class Association<TEntity, TEntity2>
    where TEntity : EntityBase
    where TEntity2 : EntityBase
{

}

Edit

If having them inherit from a common class is an issue, then this could be easily done with an interface as well.

If the Id types are important inside the Association definition, you could create an enclosing "context":

public static partial class EntityIds<TId1, TId2> {

    public class Association<TEntity1, TEntity2>
      where TEntity1 : Entity<TId1>
      where TEntity2 : Entity<TId2>
    {
      // ...
    }

}

This way, the Association class declaration is still intelligible, and it retains the necessary type arguments for its type parameters.

A factory method could help you with the normal case:

public static class AssociationFactory {
  public static EntityIds<TId1, TId2>.Association<Entity<TId1>, Entity<TId2>> Create<TId1, TId2>(/*params...*/) {
    return new EntityIds<TId1, TId2>.Association<Entity<TId1>, Entity<TId2>>(/*params...*/);
  }
}

It that looks like too much, and if you don't have entity specializations, you could model the association differently:

public class Association<TId1, TId2>
{
  // ... 
  Entity<TId1> Entity1 { get; set; }
  Entity<TId2> Entity2 { get; set; }
  // ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM