Generic class definition: type parameter's type parameter used in abstract methods

时间:2015-11-12 11:46:38

标签: c# .net generics

I'm not sure at all what keywords to use here, but: I am trying to make generic base classes for entities and collections, and do not know how to pass on the KeyType type to EntityCollection's abstract methods. The question marks hilight the problem parts.

public abstract class Entity<KeyType> {
        public KeyType id;
        public Entity(KeyType id) {
                this.id = id;
        }
}

public class Product: Entity<string> {} // Product has a string identifier

public abstract class EntityCollection<EntityType> : Where EntityType:Entity<?> {
        public abstract EntityType Get(?keytype? id);
        public abstract void Add(EntityType entity);
        public abstract IEnumerable<EntityType> GetAll();
}

public class Inventory : EntityCollection<Product> {
        public Product Get(?keytype? id) { ... }
        public void Add(Product item) { ... }
        ...
}

....

var productCode = "12345";
var list = new Inventory();
list.Add(new Product(productCode));
var foundproduct = list.Get(productCode);

Am i looking at this from the wrong angle, or missing something? I could do EntityCollection<EntityType,KeyType> : Where EntityType:Entity<KeyType>, but i feel the information is already there in the definitions and thats just duplicating it and making the definitions too complicated.

(the actual code has also interfaces, i tried to make this short)

1 个答案:

答案 0 :(得分:2)

The key to solving this is to realise that more type information is needed for EntityCollection so that you can specify the type where you have ?'s:

public abstract class EntityCollection<EntityType, T> where EntityType : Entity<T>
    {
        public abstract EntityType Get(T id);
        public abstract void Add(EntityType entity);
        public abstract IEnumerable<EntityType> GetAll();
    }

Inventory then becomes:

public class Inventory : EntityCollection<Product, string>
{
    public override Product Get(string id) { ... }
    public override void Add(Product item) { ... }
    ...
}