Why is there no IQueue<T> or IStack<T> interface in the .NET Framework? [closed]
I wanted to write an object that operated on a queue-like interface. I went searching for IQueue<T>
, but came back surprisingly empty-handed.
There are the following collection-related interfaces:
ICollection<T>
IList<T>
IDictionary<TKey,TValue>
ISet<T>
What made these types of collections get well-defined interfaces? Why do stacks and queues not warrant an interface?
Well, because there would be one to one mapping from those interfaces to classes that implement them (except latest ConcurrentQueue
). But other mentioned interfaces have lots of classes that implement them.
Expanding a bit. We can't know real motivation of BCL team. But i have a feeling that when they created Queue
and Stack
those classes looked so trivial so they decided not to abstract them out to interfaces. Reason is obvious: classes looked so simple but complete at the same time so there was no reason to create different implementations of them in BCL. Then came ConcurrentQueue
and previous statement became slightly incorrect.
As it pointed Queue
and ConcurrentQueue
don't have that much similar to make them implement single interface.
I would guess that you don't see Stack or Queue interfaces is because of the natures of the collections. The collection interfaces that you listed which do have interfaces are random access while Stacks and Queues are not. They have to be accessed in a very particular manner (FIFO or LIFO) and therefore cannot be used generally. So it makes sense to just use those collections as generic implementations but not through interfaces. In other words, because of the constraints that LIFO/FIFO put on a collection, there is very little (or nothing) that can be done differently by a class that implemented a theoretical IStack or IQueue.
To exercise this idea you could create your own IStack and/or IQueue and then implement them in a class. You will see that the functionality you expose will be completely pass-through. E.g. You will end up simply forwarding or returning requests and results to an internal Stack or Queue collection. And there will be little or nothing of potential value-added in that pass-through functionality.
Why should the .NET framework have IQueue<T>
and IStack<T>
interfaces? What would they buy?
What made these types of collections get well-defined interfaces?
The Base Class Libraries actually use all of the those interfaces (IList
etc): in each case, there are a bunch of other classes for which it made more sense to interact with the interface abstraction than a concrete type.
Why do stacks and queues not warrant an interface?
Probably because there weren't any BCL classes that needed IStack<T>
and IQueue<T>
and there were no obvious or likely use-cases for those abstractions.
I realize this isn't a satisfying philosophical answer, but it looks like the framework designers were really pragmatic about what got interfaces: they made them when they needed them.
I think the very existence of new classes in .NET 4 ConcurrentQueue<T>
and ConcurrentStack<T>
proves your point that there should have been IQueue<T>
and IStack<T>
interfaces. Even if they didn't exist originally, they should have been added in .NET 4.
I have had to create my own custom Stack implementations in the past in .NET and agree that having a standard interface would have been beneficial.
I think that's because Stack and Queue are very special concepts and to my knowledge there are no other classes implementing a special form of a stack or queue.
EDIT:
Ok, there is now a ConcurrentQueue<T>
, which seems to negate my conclusion. Maybe, back in the days when C# 1.0 was still in beta, the language designers thought there will never be a special form of a queue/stack and now it's too late to introduce an interface for it.
That's a lot of guessing. I hope, Eric Lippert will see this question and post an "official" statement. :-)
I doubt there was any particular reason. If I had my druthers, there would be a lot more discretely-defined interfaces, even if there weren't classes which implemented them alone. For example, I might have implemented a QueueStack(Of T), which would implement IGetNext(Of T), IGetNextWait(Of T), and IClear(Of T), along with IQueue(Of T), IWaitQueue(Of T), IStack(Of T), and IWaitStack(Of T). People consuming an object could specify narrowly what it was they actually needed, and implementers would only have to implement what they'd claim to support.
精彩评论