C# 堆栈对象如何处理值项

C# 堆栈对象如何处理值项,c#,.net-3.5,stack,C#,.net 3.5,Stack,假设我在班上有这个 private static Stack<int> _cursorRefCounts = new Stack<int>(); 当我调用_cursorRefCounts.Peek时,返回什么?它是一个参考还是一个值 如果我增加返回的值,然后再次调用Peek,会更大吗 我似乎记得,当它被放入堆栈对象时,int被装箱。然后当它出来的时候,它就被解开了。取消装箱是否使其再次成为值项 如果我想增加堆栈上的顶部项,我该怎么做?注意:这是一个多线程应用程序。我只想

假设我在班上有这个

private static Stack<int> _cursorRefCounts = new Stack<int>();
当我调用_cursorRefCounts.Peek时,返回什么?它是一个参考还是一个值

如果我增加返回的值,然后再次调用Peek,会更大吗

我似乎记得,当它被放入堆栈对象时,int被装箱。然后当它出来的时候,它就被解开了。取消装箱是否使其再次成为值项


如果我想增加堆栈上的顶部项,我该怎么做?注意:这是一个多线程应用程序。我只想增加最大值,而不关闭它。尽管我想我可以锁定该部分。

无论您定义为堆栈对象的泛型类型是什么类型,它都会作为该类型返回。这就是泛型的魔力。绝对不涉及装箱/拆箱,只需得到一个int

因为int是一种值类型,所以您将它作为值类型接收,而不是对该值的引用

Peek不会改变堆栈。它只是告诉你上面是什么。要修改该值,您需要首先弹出它。

Peek将返回一个值,因此增加该值不会修改堆栈上的值

要增加顶部项目,请将其弹出、增加,然后将其推回。

如前所述,Peek将返回一个值

但是,即使它返回一个装箱整数,或者如果堆栈包含一个可变引用类型,对它的任何操作都不是线程安全的

您应该简单地锁定该对象:

lock(_cursorRefCounts)
{
    int v = _cursorRefCounts.Pop();
    _cursorRefCounts.Push(v+1);
}

从理论上讲,您甚至应该使用辅助对象来锁定,但一般来说,这样做就可以了

唉,如果我弹出顶部项目,那么另一个线程出现并执行相同的操作,我可能会得到一个不同的结果,而不是仅仅找到一种增加顶部项目的方法。我可能必须将顶部项设置为对象,以便更新其内部的int。在多线程环境中,您应该使用锁使增量操作原子化。我是否可以使堆栈容纳一个包含公共int RefCount{get;set;}属性的简单对象,然后调用+++u cursorRefCounts.Peek.RefCount;?这不是线程安全吗?@Vaccano:如果另一个线程同时尝试增加值,那么它就不是线程安全的。假设RefCount=5。两个线程可以同时读取Peek结果,看到值是5,增量,然后您将得到6而不是7。您必须以某种方式锁定增量部分,因此最好使用更简单的堆栈实现。@vacca:++运算符不是线程安全的。根据经验,语言或库中的任何内容都不是线程安全的,除非有明确的安全文档记录。听起来您为该作业选择了错误的集合类。您不应该需要修改堆栈中包含的值。@Cody Gray-为什么不呢?如果我创建了一个简单的对象,其中包含一个名为RefCount的int属性,那么我可以说+++_cursorRefCounts.Peek.RefCount;