Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have two interfaces, one with and one without generic type parameters. The non-generic interface is used internally so that I can store instances of the generic interface in a collection. All would be well except for the fact that C# does not generate method signatures based on the return type. I have a method in each interface called GetItems. One returns an IList the other an IList<T>. Since I cannot give them both the same name I need to come up with two different names that both convey what they do. Here are the interfaces:

public interface IBatchProcessingStorage {
    void Enqueue(object o);
    void Enqueue(IEnumerable items);
    void Dequeue(object o);
    void Dequeue(IEnumerable items);
    IList GetItems(int maxItems);
}
public interface IBatchProcessingStorage<T> : IBatchProcessingStorage {
    void Enqueue(T item);
    void Enqueue(IEnumerable<T> item);
    void Dequeue(T item);
    void Dequeue(IEnumerable<T> item);
    IList<T> GetItems(int maxItems);
}

There is a task that runs every so often that will get items from the batch processing store, pass them to an external resource, and if they are processed by the external resource then they are removed from the store. The task needs the non-generic interface, that is the only reason it exists. I have created an abstract class that implements both, and redirects the calls in the non-generic interface to the generic ones and the generic ones are abstract like so:

public abstract class BatchProcessingStorage<T> 
  : IBatchProcessingStorage<T>
  , IBatchProcessingStorage {

    void IBatchProcessingStorage.Enqueue(object o) { Enqueue((T)o); }

    void IBatchProcessingStorage.Enqueue(IEnumerable items) {
        Enqueue((IEnumerable<T>)items); }

    void IBatchProcessingStorage.Dequeue(object o) { 
        Dequeue((T)o); }

    void IBatchProcessingStorage.Dequeue(IEnumerable items) {
        Dequeue((IEnumerable<T>)items); }

    IList IBatchProcessingStorage.GetItems(int maxItems) {
        return this.GetItems(maxItems).ToArray(); }

    public abstract void Enqueue(T item);

    public abstract void Enqueue(IEnumerable<T> item);

    public abstract void Dequeue(T item);

    public abstract void Dequeue(IEnumerable<T> item);

    public abstract IList<T> GetItems(int maxItems);
}

This is supposed to be the class that customers will inherit from, but I'm not going to force them into our inheritance hierarchy. So they may have to implement both interfaces. This is the reason for my great concern about the names. I don't want our API to have crap method names. So, what should I call GetItems in each class that conveys meaning without looking like I'm working around language limitations?

Update:

For those of you who think I am over analyzing this: We have learned a lot about our public API over the past 5 years. I have one chance to get this new one right. After that we are stuck with what is released. This is not your average internal software application. It is a software platform that is very extensible. It is used by some of the most well known companies in the world. It is going to be very hard for them to honestly get on stage at our conferences and tout the usefulness of our software platform, if It has a crappy API. This is not overly complex, or overly abstract. It is designed to serve a specific business need. Our customers are going to need this, better yet, they already do through a very poorly named, and overly complex API that makes you jump through hoops to get things done (hindsight is always 20/20).

share|improve this question
    
Dude, I think you are making this overly complex and overly abstract. YAGNI. –  Ed Niell Apr 23 '11 at 10:07
3  
This might be better for Code Review. –  Jon Purdy Apr 23 '11 at 18:24
    
@Jon - is naming conventions independent of programming languages more proper for the code review site or here? I'm fairly new to stackexchange in general. –  Charles Lambert Apr 23 '11 at 18:30
    
@Charles I'd agree with @Jon Purdy. It's not wrong to post it here, but you might get a better response from Code Review. –  Tieson T. Apr 23 '11 at 18:35
    
Fair enough. I just want the best possible chance of getting answers, and knowing in advance on where to post them helps. Thanks –  Charles Lambert Apr 23 '11 at 18:40

3 Answers 3

This is the perfect use case for explicit interface implementation. Simply use explicit interface implementation for the non-generic interface and then the one caller who needs that interface can call directly through the non-generic interface and both interfaces can have the proper friendly method name without conflicting with each other.

share|improve this answer
    
That is already a requirement for using both interfaces directly. The abstract base class in my question does this already. I didn't express this requirement in my question. –  Charles Lambert Apr 25 '11 at 21:49

Two suggestions.

  1. Don't name the class BatchProcessingStorage, name it BatchProcessingStorageSystem.
  2. Don't expose enqueue and dequeue functions unless the class is called FooQueue

You're exposing a tad too much information in this API. First, no one should know or care that you enqueue or dequeue. If it is necessary that people know that you're using some sort of LIFO list, that's OK, but they shouldn't have to enqueue and dequeue, they should just add and get.

And, if your class is the Storage, then the person implementing it might expect more control over the class than you're willing to expose in the API, if you call it BatchProcessingStorageSystem, then you can expose what needs to be exposed, when it needs to be exposed.

share|improve this answer
    
these names have not been finalized yet. I originally had Add, Remove, and Get instead of what is listed here. We don't implement it as a queue, but the easiest way for our customers to integrate with our product would be to implement it as a queue. It might be a hard sell, but the more I think about it, the more it should be a queue. –  Charles Lambert Apr 26 '11 at 0:20
up vote 0 down vote accepted

There is no need to generate a new name for either method here. By adding the 'new' keyword to the GetItems method defined in IBatchProcessingStorage<T>, you can give both methods the same name when you explicitly define one of the interfaces in an implementing class.

public interface IBatchProcessingStorage {
    void Enqueue(object o);
    void Enqueue(IEnumerable items);
    void Dequeue(object o);
    void Dequeue(IEnumerable items);
    IList GetItems(int maxItems);
}
public interface IBatchProcessingStorage<T> : IBatchProcessingStorage {
    void Enqueue(T item);
    void Enqueue(IEnumerable<T> item);
    void Dequeue(T item);
    void Dequeue(IEnumerable<T> item);
    new IList<T> GetItems(int maxItems);
}

Apparently I failed to notice that what was being generated was a compiler warning and not an error. I despise and treat them both equally. Since I already expect them to be explicitly implementing the non-generic interface to call the non-generic methods, this method hiding is acceptable behavior.

share|improve this answer
    
You answered a different question than the one you asked: How do I make the warning go away when I redefine a non-virtual function? –  Rick Sladkey Apr 25 '11 at 22:18
    
@Rick - If you update your answer to also mention using the new keyword to get rid of the compiler warning, I will mark yours as the answer. –  Charles Lambert Apr 25 '11 at 23:04
    
@Rick - Just doing what your originally said, does not remove the compiler warning, which is not good –  Charles Lambert Apr 25 '11 at 23:09
    
No problem. If you think "new" is the correct answer to the question you asked, that's up to you. –  Rick Sladkey Apr 25 '11 at 23:40
    
@Rick - I think it completes the answer you originally gave. Your answer is what triggered me to figure out my solution. Until today I did not know you could use the new keyword on methods defined in an interface. –  Charles Lambert Apr 26 '11 at 0:34

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.