41

Is there some other way, except Stack<T>.Count() == 0, to check if a Stack<T> is empty?

Coming from C++/Java background where "stack" classes generally have some sort of dedicated "is empty" method like Java - Stack.empty.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
BobsunShirov
  • 447
  • 1
  • 4
  • 6
  • 1
    https://answers.yahoo.com/question/index?qid=20120403003525AAWPFlt – eddie_cat Sep 09 '14 at 15:47
  • Imho that is a very readable and efficient way. So no, i don't know a better way since [`Peek`](http://msdn.microsoft.com/en-us/library/1w32446f(v=vs.110).aspx) is not an option. – Tim Schmelter Sep 09 '14 at 15:48
  • 2
    You could use `Any` I believe. `var notEmpty = stack.Any()`. To be clear, like @TimSchmelter is saying below, this is not as effecient as using `Count` property. – Neil Smith Sep 09 '14 at 15:48
  • If you really want IsEmpty or Empty then you could use an extension method, but that's just wrapping this Count == 0. I think Count is perfectly readable. – tbddeveloper Sep 09 '14 at 15:49
  • try { stack.pop(); }catch{ // empty! } Don't do that. – xlecoustillier Sep 09 '14 at 15:50
  • @TimSchmelter - I agree, just answering since he was asking for another way. Just realized he was using the Count extension instead of Stack's Count property though. – Neil Smith Sep 09 '14 at 15:50
  • @NeilSmith: but has unnecessary overhead because it needs to create the enumerator. – Tim Schmelter Sep 09 '14 at 15:50
  • @TimSchmelter That's a pretty tiny issue. You're well in the ballpark of microoptimizations that are going to be irrelevant in almost all contexts. – Servy Sep 09 '14 at 16:01
  • @servy: is this micro optimization:`while(stack.Count > 0){}` as opposed to `while(stack.Any()){}`? The Count property is a no-op. Unlike Enumerable.Count which uses the Count property Enumerable.Any is not optimized. – Tim Schmelter Sep 09 '14 at 16:11
  • @TimSchmelter However `Any` will only need to call `MoveNext` once on the iterator, so it will still be blazingly fast. It doesn't *need* that optimization; adding it would likely *slow it down*. – Servy Sep 09 '14 at 16:14
  • @TimSchmelter if you find that `Count()` or `Any()` for `Stack` causing performance issue you simply can add you own extension to override default `Enumerable.Any` ones by specifying exact type and be done (it is even already done for `Count()` as `Stack` is `ICollection>`). – Alexei Levenkov Sep 09 '14 at 16:19
  • 1
    @AlexeiLevenkov: i can write extensions for everything. But in my opinion extensions have disadvantages and should add more than a simple Any to Count translation, thats just confusing. Instead of remembering that its better to use Count you have to remember that you have to use the extension. – Tim Schmelter Sep 09 '14 at 16:22
  • @servy: is that true? We are talking about an (possibly infinite) while-loop which needs to execute Any on every iteration. I am not convinced since even Marc Gravell suggests Count on a collection: http://stackoverflow.com/a/305156/284240 – Tim Schmelter Sep 09 '14 at 16:38
  • @TimSchmelter You'd have to actually profile it in context to be sure. It's primarily going to be dependant on what all of the rest of the code is doing. If the body of the loop is something that can run in just a handful of processor cycles, and the loop runs for a *very* long time, then sure, it could matter. If the body of the loop isn't *super* trivial, or the loop doesn't run for many millions of iterations, then it's unlikely to be an issue. – Servy Sep 09 '14 at 16:42

4 Answers4

59

Instead of using .Count() == 0, just use .Count == 0. This is using the stack's property rather than the linq extension method.

recursive
  • 83,943
  • 34
  • 151
  • 241
  • 10
    Just for information: in practise this doesn't matter a lot because `Stack` implements `ICollection` and in that case `Enumerable.Count` simply uses the `Count` property too. – Dirk Sep 09 '14 at 15:57
  • I'd argue that `.Count` is faster than `.Count()`. [See the answer by @StriplingWarrior for proof](https://stackoverflow.com/a/54371755/5161361) – Fortune Sep 15 '22 at 09:40
32

There are three common approaches, and which one you use will usually be a matter of taste.

if(!stack.Any()) ...
if(stack.Count() == 0) ...
if(stack.Count == 0) ...

Profiling the different approaches looks like this:

Benchmark

.Any() and .Count() take 10x-20x longer than .Count... and can still run tens of thousands of times per millisecond. So .Count > 0 is "much faster", but the others are still fast enough to not have to worry about under most circumstances. I'd personally stick with Any() since I feel it reads better, but I wouldn't give anyone flak for choosing Count.

Update

Running the same LINQPad Script in .NET 6, with optimization turned on, shows that !stack.Any() is actually faster now than stack.Count() == 0, though it's still an order of magnitude slower than stack.Count == 0. My initial assessment remains unchanged.

enter image description here

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • 1
    Thanks for this answer, especially the benchmarks. :-) Currently writing a compiler, so performance is important in my case. – Per Lundberg Jan 25 '20 at 21:01
4

You can create your own extension method too

namespace System.Collection.Generic {
   public static class SystemEx {
        public static bool IsEmpty<T>(this Stack<T> stack) {
            return (stack.Count==0);
        }    
   }
Blau
  • 5,742
  • 1
  • 18
  • 27
  • 4
    Some extensions are just redundant. This is one of them. It just hides the implementation which is not complex. So we always have to look why the method exists at all, maybe there is an important detail. – Tim Schmelter Sep 09 '14 at 16:17
  • I agree with you, but we are not discussing whether it's convenient or not, only if it can be done in other way. ;) – Blau Sep 09 '14 at 16:32
1

You can use stack.Any(). Fast, readable, and standard way for all IEnumerable<T> objects.