调用Queue.Enqueue方法时会发生什么异常/错误

时间:2014-01-16 14:36:13

标签: c# queue

在MSDN和Intellisense信息中,没有提到调用Queue.Enqueue方法时抛出的任何异常

但是自从MSDN说

  

.....当元素添加到队列时,容量会根据需要通过重新分配自动增加

我想它可能会失败,因为没有足够的内存来容纳新元素。

callin Queue.Enqueue方法可能会发生哪些其他错误? 也许答案可能包括链接到文档列出所有这些特定方法的文档

即使没有抛出该方法,如何在调用该方法时捕获/处理OutOfMemoryException?(即使我无法从OutOfMemory错误中恢复,我想记录它)

并且“不被抛出”我的意思是

在任何方法的文档中,它总是提到该方法可以抛出哪些异常,但是对于该特定方法要么没有记录,要么它不会抛出任何异常。我想知道它是哪一个

3 个答案:

答案 0 :(得分:1)

以下是Enqueue方法的反汇编(取自ILSpy)

public void Enqueue(T item)
{
    if (this._size == this._array.Length)
    {
        int num = (int)((long)this._array.Length * 200L / 100L);
        if (num < this._array.Length + 4)
        {
            num = this._array.Length + 4;
        }
        this.SetCapacity(num);
    }
    this._array[this._tail] = item;
    this._tail = (this._tail + 1) % this._array.Length;
    this._size++;
    this._version++;
}

private void SetCapacity(int capacity)
{
    T[] array = new T[capacity];
    if (this._size > 0)
    {
        if (this._head < this._tail)
        {
            Array.Copy(this._array, this._head, array, 0, this._size);
        }
        else
        {
            Array.Copy(this._array, this._head, array, 0, this._array.Length - this._head);
            Array.Copy(this._array, 0, array, this._array.Length - this._head, this._tail);
        }
    }
    this._array = array;
    this._head = 0;
    this._tail = ((this._size == capacity) ? 0 : this._size);
    this._version++;
}

正如您所看到的,它非常简单。您可以获得StackOverflowExceptionOutOfMemoryException,因为您总是可能会获得这些内容。

除此之外,不清楚任何事情都可能出错。您需要通过验证其余代码中的各种检查和保护子句来验证不存在NullPointerException的可能性,但粗略的一瞥表明这可能不会发生。当然,如果你开始使用反射,你总是可以强制抛出NullPointerException。

我不知道这会对你有所帮助,但我相信它会回答你提出的问题。

答案 1 :(得分:0)

看过你的编辑后,问题会更有意义。

MSDN文档通常不会记录可以抛出OutOfMemoryException,因为基本上,任何方法调用都可以抛出它(任何分配内存的方法 - 这几乎都是它们!)。因此,您可以假设在这种情况下可以抛出它。


为了澄清捕获异常的情况,想象一下这段代码:

  try
  {
      throw new ArgumentNullException();
  }
  catch (ArgumentOutOfRangeException)
  { 
      // This can never happen, but is perfectly legal code.
  }

永远不会输入catch块,但编译器对此代码非常满意 - 它甚至不会发出警告。

答案 2 :(得分:0)

如果您的唯一目标是捕获所有可能的exec并记录它们而不执行任何其他操作,那么它实际上非常简单。

try
{
    queue.Enqueue(foo);
}
catch (Exception ex)
{
    LoggingMethod(ex);
    throw;
}

它将捕获所有可能捕获的异常(OutOfMemory是您可能无法做到的少数异常之一),记录它,然后在保留原始堆栈跟踪的同时重新抛出异常,因此代码为如果需要,可以处理它的代码片段。

执行throw ex;,这会导致重新创建堆栈跟踪以指向throw ex行,并且您将不知道哪一行代码真正的例外被抛出。