I have two interfaces; ISet and ISet<T>
Both implement Add, Remove and Clear but with different argument types; object and T.
Now I have two options. Either let ISet<T> inherit from ISet, or let them be isolated from each other.
One great benefit of having ISet<T> inherit from ISet is of course that I always can use a ISet<T> where-ever I need a ISet. But doing so I also have to add the “new” modifier to the members with a T-parameter. I don’t like the “new”-modifier very much, but maybee this is the better option in this case?
It feels odd having a ISet<T> that isn’t also a ISet. That’s the logical assumption. I can’t really say excatly why I don’t like the “new”-modifier. It’s like with the “goto”-keyword. I just try not to use it.
What do you think I should go with here? Inherit or not?
In .NET we have ICollection<T> and ICollection which doesn’t inherit. Neither do IList<T> and IList. But IEnumerable<T> inherit from IEnumerable.
I know about the ISet-interface that allready exist (This was just an example)
The only thing that inheriting from the non-generic form would really buy you is the ability to perform certain operations on an
ISet<T>without having to know at compile time what theTwas. One couldn’t add items to such a set in type-safe manner, and reading might be somewhat inefficient (since value types would have to be boxed), but methods or properties likeCountcould be perfectly useful.My suggestion would be that you define multiple interfaces something like this (note that I’m adding some members that you don’t have, since your collection is at moment write-only and thus not very useful)
interface ICountable { int Count {get;} } interface IClearable { int Count {get;} } interface IAppendable<in T> { void Add(T item); } interface ICountableEnumerable<out T> : IConvertableToEnumerable, ICountable {IEnumerable<T> CopyAsEnumerable();} interface IFetchable<out T> { T FetchAndRemove(ref bool wasNonEmpty); } interface ISet<T> ICountable, IClearable, IAppendable<T>, IFetchable<T>, IConvertableToEnumerable<T>;Such interface segregation makes it possible to use covariance and contravariance to the extent that it makes sense.