简体   繁体   中英

Abstract base class that inherits ICollection<T>

Suppose I have an abstract base class BaseTimeCollection and at least one concrete class ConcreteTimeCollection which inherits from the base class.

I would like my base class to inherit from ICollection<T> .

Inheriting from ICollection<T> requires me to 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 concrete classes.

This is where I run into trouble.

The GetEnumerator methods need to be declared explicitly, because there are two of them both with the same name but 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 my 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()
    }
}
  1. What have I missed?

  2. Is there some way I can defer implementation of the GetEnumerator methods to the concrete classes?

You can easily defer the implementation to your child classes by having the explicit implementations call protected abstract methods in your abstract class and then letting the children implement those 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 scheme...it's the best I could come up with this early in the morning.

It's not necessary to implement both versions of GetEnumerator explicitly to prevent the name clash, so unless there's another requirement for them both to be explicit, you could make the generic method implicit so that it can also be abstract. Then, as per @supercat, the non-generic method can call the 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) ...
}

First of all: What is the compile error you are getting?

Do you need your base class, maybe you can just use another interface like:

public interface BaseTimeCollection : ICollection<Time> {}

and then have your implementations implement that interface instead of your base class, or do you have some common functionality?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM