如何检查 Stack<T> 是否为空

41

除了 Stack<T>.Count() == 0 这种方式,是否有其他方法可以检查 Stack<T> 是否为空?

来自 C++/Java 背景的开发者通常会使用类似于 Java - Stack.empty 的专用“是否为空”方法。


1
https://answers.yahoo.com/question/index?qid=20120403003525AAWPFlt - eddie_cat
2
你可以使用 Anyvar notEmpty = stack.Any()。要明确的是,就像下面@TimSchmelter所说的那样,这不如使用 Count 属性有效率。 - Neil Smith
如果你真的想要使用IsEmpty或Empty,那么你可以使用扩展方法,但这只是将Count == 0进行了包装。我认为Count已经足够易读了。 - tbddeveloper
尝试 { stack.pop(); }catch{ // 空的! } 不要这样做。 - xlecoustillier
1
@AlexeiLevenkov:我可以为任何东西编写扩展。但在我看来,扩展有一些缺点,应该提供比简单的Any到Count转换更多的功能,否则会让人感到困惑。与其记住最好使用Count,不如记住必须使用扩展。 - Tim Schmelter
显示剩余10条评论
4个回答

60

不要使用.Count() == 0,而是直接使用.Count == 0。这样可以使用堆栈的属性而不是linq扩展方法。


10
仅供参考:实际上这并不太重要,因为 Stack<T> 实现了 ICollection 接口,在这种情况下,Enumerable.Count 简单地使用了 Count 属性。 - Dirk
我认为.Count.Count()更快。请查看@StriplingWarrior的答案以获得证明 - Fortune

33

有三种常见的方法,使用哪一种通常是品味问题。

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

对不同方法进行剖析看起来像这样:

Benchmark

.Any().Count()需要比.Count慢10倍至20倍,但仍可每毫秒运行数万次。因此,.Count > 0是“更快的”,但其他情况下也足够快,无需担心。我个人会坚持使用 Any(),因为我感觉它读起来更好,但我不会因为选择 Count 而责备任何人。

更新

在打开优化后的 .NET 6 中运行相同的 LINQPad 脚本表明,!stack.Any()实际上比stack.Count() == 0更快了,尽管它仍然比stack.Count == 0慢一个数量级。我的初始评估没有改变。

enter image description here


1
感谢您的回答,尤其是提供了基准测试数据。 :-) 我目前正在编写一个编译器,因此性能对我来说非常重要。 - Per Lundberg

4
你也可以创建自己的扩展方法。
namespace System.Collection.Generic {
   public static class SystemEx {
        public static bool IsEmpty<T>(this Stack<T> stack) {
            return (stack.Count==0);
        }    
   }

4
有些扩展功能是多余的,这就是其中之一。它只是隐藏了并不复杂的实现细节。因此,我们总是要思考为什么方法存在,也许有重要的细节需要考虑。 - Tim Schmelter
我同意你的观点,但我们讨论的不是方便与否,而是是否有其他方法可以实现。 ;) - Blau

1
你可以使用 stack.Any()。这是对于所有 IEnumerable<T> 对象来说,快速、易读和标准的方法。

2
查看由@StriplingWarrior提供的基准测试。 - PAS
我知道(过了一段时间后我离开了这个领域,但是...)所以我没有说Any()是“最快”的。但它足够快。Count == 0只适用于IList,对我来说不够通用。Count() == 0是最糟糕的,因为它不仅速度慢,而且是O(n),而Count==0Any()是O(1)。 但是Any()既通用又足够快。如果你需要最快的选项,比如游戏开发,那么...我想你需要用C++。如果你正在开发服务器端,例如拥有合理计算能力的情况下,Any()是你的朋友,我个人认为。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接