如何正确清除包含结构的队列?

How to properly Clear a Queue containing structs?

我已经声明了一个像这样的基本结构

private struct ValLine {
  public string val;
  public ulong linenum;
}

并像这样声明一个队列

Queue<ValLine> check = new Queue<ValLine>();

然后在使用 StreamReader 的设置中,我在 while 循环中使用 ReadLine 读取输入文件的行,除其他外,我这样做是为了填充队列:

check.Enqueue(new ValLine { val = line, linenum = linenum });

("line" 是包含每一行文本的字符串,"linenum" 只是一个计数器,初始化为 0,每次循环递增。)

"check" 队列的目的是,如果特定行满足某些条件,那么我将该行存储在 "check" 中,连同它在输入文件中出现的行号。

在我读完输入文件后,我使用 "check" 做各种事情,但是当我完成使用它时,我以明显的方式清除它:

check.Clear();

(或者,在我通过 "check" 的最后一个循环中,我可以只使用 .Dequeue(),而不是 foreach'ing。)

但后来我开始思考 - 等一下,我首先填充队列时生成的所有 "new ValLine" 怎么办???我造成了内存泄漏吗?我是 C# 的新手,所以我不清楚如何处理这个问题——或者即使它应该被处理(也许 .Clear() 或 .Dequeue() 会自动处理现在已过时的结构?)。我和我们亲爱的朋友 Google 一起度过了一个多小时,只是没有找到关于清除结构集合的此类示例的任何具体讨论。

那么...在 C# 中,我们是否需要在清除队列(或出队时)之前处理清除单个结构的问题?如果是这样,那么正确的方法是什么?

(以防万一,我在 Visual Studio 2013 年使用 .NET 4.5。)

更新:这是为了将来参考(你知道,如果这个页面出现在 Google 搜索中)关于正确的编码。为了按照建议使结构不可变,这就是我最终得到的结果:

private struct ValLine {
  private readonly string _val;
  private readonly ulong _linenum;
  public string val { get { return _val; } }
  public ulong linenum { get { return _linenum; } }
  public ValLine(string x, ulong n) { _val = x; _linenum = n; }
}

对应于该更改,队列人口行现在是这样的:

check.Enqueue(new ValLine(line,linenum));

此外,虽然不是绝对必要,但我确实摆脱了队列中的 foreach(和 check.Clear();,并将其更改为

while (check.Count > 0) {
  ValLine ll = check.Dequeue();
  writer.WriteLine("[{0}] {1}", ll.linenum, ll.val);
}

以便在输出信息的同时清空队列。

更新 2:好的,是的,我仍然是 C# 新手(不到一年)。我从网上学到了很多东西,当然,我经常看的是一年多以前的例子。我已经更改了我的结构,所以现在它看起来像这样:

private struct ValLine {
  public string val { get; private set; }
  public ulong linenum { get; private set; }
  public ValLine(string x, ulong n): this()
    { this.val = x; this.linenum = n; }
}

有趣的是,在想出第一次更新(上图)中的内容之前,我实际上已经完全尝试了这个,但是出现了编译错误(因为我没有 : this()与构造函数)。根据进一步的建议,我进一步检查并发现了一个最近的例子,显示 : this() 使它像我之前尝试的那样工作,插入它,然后 - Wa La! - 干净的编译。我喜欢代码更简洁的外观。私有变量叫什么与我无关

不,您不会造成内存泄漏。调用 ClearDequeue 将适当地清除内存 - 例如,如果你有一个 List<T> 那么一个清除操作可能会使用:

for (int i = 0; i < capacity; i++)
{
    array[i] = default(T);
}

我不知道 Queue<T> 是用建立在数组上的循环缓冲区还是链表实现的 - 但无论哪种方式,你都会没事的。

话虽如此,我会强烈建议不要像您在这里所做的那样使用可变结构以及可变字段。虽然它不会导致您设想的特定问题,但它们的行为方式可能会令人困惑。