c# - C# 的 Queue.dequeue() 是按引用传递还是按值传递?
问题描述
所以我试图使用队列来创建一个对象池以回收它们。在实现它之后,我似乎仍然获得相同级别的内存使用。我很难理解使用 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);
}
我预计这种方法的内存使用率会很低或没有,但它保持不变。感谢您的帮助!:)
解决方案
当您调用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
。)
我之所以将其包括在内,是因为似乎有必要逐字回答您的问题。出于实际目的,您可能在需要它之前并不关心它。我毫不怀疑添加它是有原因的,但我也没有使用它。
推荐阅读
- jsp - @FormParam 和 ${param} 之间的冲突
- r - 如何在ggnet2(R)中自动调整节点和标签大小
- html - 如何将 3 个点放在 CSS 中多行文本的第 3 行的最后一个单词中
- ubuntu - 运行 PHPUnit 使用过多的磁盘空间
- android - 将音频流/Uint8List 数据保存在文件颤动中
- flutter - Flutter 上的视频编辑器
- reactjs - 如何模拟 window.gapi.load() React + Jest
- git - 是否有一种简单的方法可以查看参与合并冲突的开发人员?
- android - 由于在 Android BLE 上达到最大连接数限制,获取连接失败的任何错误代码
- swift - Swift Combine:将错误转化为发布者的输出