C#的Queue.dequeue()是通过引用还是通过值传递的?

时间:2019-05-10 16:32:11

标签: c# queue

因此,我尝试使用队列创建对象池以回收它们。在实现它之后,我似乎仍然获得相同级别的内存使用率。我正在努力了解使用queue()还是dequeue()是通过引用还是通过值。

void ClearNodeListandBackupToPool(ref List<Node> nodelist)    
{    
    foreach (var node in nodelist)    
    {    
        nodePool.Enqueue(node);    
    }

    nodelist.Clear();    
}

Node CreateNewNode(Vector2 tile, Node parent, double gCost, double hCost)    
{    
    if (nodePool.Count > 0)    
        return nodePool.Dequeue().init(tile, parent, gCost, hCost);    

    return new Node(tile,parent,gCost,hCost);    
}

我希望此方法的内存使用率很低或没有,但它保持不变。谢谢您的帮助! :)

1 个答案:

答案 0 :(得分:0)

调用Dequeue时,返回的值是对返回对象的引用。在解释这意味着什么之前,先说出为什么对您可能无关紧要:

如果您这样做:

var list = new List<Object>();
list.Add(new object());
var o = list[0];

现在有两个引用相同的对象。 list有一个参考,而o有另一个参考。如果o超出范围,但list没有超出范围,则该对象将不会被垃圾回收,因为仍然存在对该对象的引用。

如果您这样做:

var queue = new Queue<Object>();
queue.Enqueue(new object());
var o = queue.Dequeue();

队列中只有一个对对象的引用。为什么?因为一旦将其从队列中取出,该项目便已从队列中删除,因此队列不再有对其的引用。 o是唯一的引用,并且如果o超出范围,则对象将被垃圾回收,因为不再有对其的引用。

对象是通过值还是通过引用返回的问题并不重要。

按值返回引用是什么意思?

在上面的示例中,使用列表,list[0]返回一个值,该值是对该对象的引用。如果我们这样做:

var list = new List<Object>();
list.Add(new object());
var o = list[0];
o = "x";

... o现在引用一个字符串,但是列表中的项目未更改。尚未替换为“ x”。这是因为从列表中检索该项目会返回一个值,即对该对象的引用的副本。我们尚未检索到实际参考。因此,o = "x";替换了列表返回的引用的副本,而不是列表中包含的实际引用。

其他人观察到-我同意-理解行为要比用语言表达要容易得多。这些示例很容易理解,但是对发生的事情的描述却并非如此。

C#7引入了ref returns。这允许方法通过引用返回对象。这意味着该方法返回其自己的引用。很容易发现,因为在调用方法时会使用ref关键字,例如ref var object = ref queue.Dequeue()。 (您不能这样做,因为Dequeue不使用ref returns。)

我只包括这一点,因为似乎确实需要回答您的问题。出于实际目的,您可能不关心它,直到需要它为止。我毫不怀疑添加它是有原因的,但是我也没有使用它。