An abstract base class that inherits ICollection <T>
Suppose I have an abstract base class BaseTimeCollection and at least one concrete class ConcreteTimeCollection that inherits from the base class.
I would like my base class to inherit from ICollection<T> .
Inheriting from ICollection<T> requires that I provide implementations for a number of methods, including IEnumerable.GetEnumerator() and IEnumerable<T>.GetEnumerator .
I do not want to implement these methods in BaseTimeCollection - instead, I would prefer to implement them individually in each of my specific classes.
Here I ran into difficulties.
GetEnumerator methods must be declared explicitly because there are two of them with the same name but with different return types. However, it seems that as soon as I make the signature explicit, I can no longer use the abstract modifier. Essentially, I am forced to implement the GetEnumerator method in a base class.
public abstract class BaseTimeCollection : ICollection<Time> { abstract IEnumerator IEnumerable.GetEnumerator(); // compile error: The modifier 'abstract' is not valid for this item abstract IEnumerator<Time> IEnumerable<Time>.GetEnumerator(); // compile error: The modifier 'abstract' is not valid for this item } public class ConcreteTimeCollection : BaseTimeCollection { IEnumerator IEnumerable.GetEnumerator() { // this is where I would like to provide my implementation for IEnumerable.GetEnumerator() } IEnumerator<Time> IEnumerable<Time>.GetEnumerator() { // this is where I would like to provide my implementation for IEnumerable<Time>.GetEnumerator() } } What did I miss?
Is there a way to defer implementation of
GetEnumeratormethods for specific classes?
You can easily defer an implementation to your child classes, indicating that explicit implementations invoke protected abstract methods in your abstract class, and then allow children to implement these abstract methods:
public abstract class BaseTimeCollection : ICollection<Time> { protected abstract IEnumerator IEnumerable_GetEnumerator(); protected abstract IEnumerator<Time> GenericEnumerable_GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() { return IEnumerable_GetEnumerator(); } IEnumerator<Time> IEnumerable<Time>.GetEnumerator() { return GenericEnumerable_GetEnumerator(); } } Sorry for the poor naming schemes ... this is the best I could come up with in the early morning.
First of all: What compilation error do you get?
You need your base class, maybe you can just use a different interface, for example:
public interface BaseTimeCollection : ICollection<Time> {} and then your implementations implement this interface instead of your base class or do you have common functions?
You do not need to explicitly use both versions of GetEnumerator to prevent name collisions, so if there is no other requirement that they be explicit, you could make the general method implicit so that it can also be abstract. Then, according to @supercat, a non-generic method can call a generic one.
public abstract class BaseTimeCollection<Time> : ICollection<Time> { public abstract IEnumerator<Time> GetEnumerator(); // implicit, generic and abstract IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } // Other ICollection methods (Add, Clear, etc) ... }