This is class design question.
I have main abstract class
public abstract class AbstractBlockRule
{
public long Id{get;set;}
public abstract List<IRestriction> Restrictions {get;};
}
public interface IRestriction{}
public interface IRestriction<T>:IRestriction where T:struct
{
T Limit {get;}
}
public TimeRestriction:IRestriction<TimeSpan>
{
public TimeSpan Limit{get;set;}
}
public AgeRestriction:IRestriction<int>
{
public int Limit{get;set;}
}
public class BlockRule:AbstractBlockRule
{
public virtual List<IRestriction> Restrictions {get;set;}
}
BlockRule rule=new BlockRule();
TimeRestriction t=new TimeRestriction();
AgeRestriction a=new AgeRestriction();
rule.Restrictions.Add(t);
rule.Restrictions.Add(a);
I have to use non-generic Interface IRestriction just to avoid specifying generic type T in main abstract class. I'm very new to generics. Can some one let me know how to better design this thing?
The runtime treats
IRestriction<TimeSpan>
andIRestriction<int>
as different distinct classes (they even have their own set of static variables). In your case the only classes common to bothIRestriction<TimeSpan>
andIRestriction<int>
in the inheritance hierarchy areIRestriction
andobject
.So indeed, having a list of
IRestriction
is the only sensible way to go.As a side note: you have a property
Limit
in there that you might want to access regardless of whether you're dealing with anIRestriction<TimeSpan>
orIRestriction<int>
. What I would do in this case is to define another propertyobject Limit { get; }
onIRestriction
, and hide it in the actual implementation. Like this:This way you can access
Limit
asobject
on all yourIRestriction
when you don't care what type it is. For example:Interfaces are contracts that need to be followed by the entity that implements the contract.
You have created two contract with the same name
IRestriction
As far as I can see, what you are basically may need is a flag for classes that can be restricted, which should implement the
IRestriction
non-generic interface.The second interface seems to be restrictable objects that also contain a limit property. Hence the definition of the second
IRestriction
interface can beILimitRestriction
or whatever name suits your business needs.Hence
ILimitRestriction
can inherit fromIRestriction
which would mark classes inheritingILimitRestriction
still objects ofIRestriction
Your approach is typical (for example, IEnumerable<T> implements IEnumerable like this). If you want to provide maximum utility to consumers of your code, it would be nice to provide a non-generic accessor on the non-generic interface, then hide it in the generic implementation. For example:
I also showed using a base restriction class here, but it is not required.