Let's assume I have:
- A generic method
Get<T>
- A few interfaces
IEntity
,IValue
- A few classes that respectively implements those interfaces ex:
Entity
->IEntity
,Value
->IValue
etc.
=> Is there a way for the Get<T>
method to allow the interfaces only as generic Types?
Get<IEntity>(42); //Allowed
Get<Entity>(42); //Compiler error
My current solution looks like this:
- A generic method
Get<T>
with a Type constraintwhere T: IPersistable
(to prevent most of the types to be passed as a parameter) - The interfaces implement
IPersistable
The function actively checks the type:
public T Get<T>(long id) where T : IPersistable
{
if (typeof (T) == typeof (IEntity))
return (T) EntityDao.Get(id);
if (typeof (T) == typeof (IValue))
return (T) ValueDao.Get(id);
//...
throw new TechnicalException("Type not supported");
}
=> The problem are:
- It is not clean... I could live with that since there are only very few types to check from
- The signature does not match what the function really does. It allows an
IPersistable
in, but not really <- that really bugs me :(
Edit: I'm considering such constraints to avoid surpopulation of my class.
I have something like 8 or 9 generic methods in that class that all pretty much work this way. The intuitive way of doing would be as @DanielHilgarth suggested to have 1 method per type only. The methods currently can be called with 4 or 5 types only. But still, that would mean 32-40 methods in that class.
If possible I'd like to avoid that.
Edit2: the need for preventing "real" classes to be called comes from a covariance/contravariance problem. The EntityDao and ValueDao Get<T>
methods return IEntity
and IValue
objects. What works fine when I query for a single object fails when I call for a collection in a GetAll<T>
methods since I cannot cast an IEnumerable<IValue>
in an IEnumerable<Value>
.
I just noticed this answer from @JonSkeets about casting of lists. That could be a workaround...