title: Releasing COM objects in .NET from within enumerations and other reference scenarios
body: <p>I have a WinForms application that uses COM Interop to connect to Microsoft Office applications. I have read a great deal of material regarding how to properly dispose of COM objects and here is typical code from my application using techniques from Microsoft's own article (<a href="http://msdn.microsoft.com/en-us/library/aa679807%28v=office.11%29.aspx" rel="nofollow">here</a>):</p>
  
  <pre><code>Excel.Application excel = new Excel.Application();
  Excel.Workbook book = excel.Workbooks.Add();
  Excel.Range range = null;
  
  foreach (Excel.Worksheet sheet in book.Sheets)
  {
      range = sheet.Range["A2:Z2"];
  
      // Process [range] here.
      range.MergeCells();
  
      System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
      range = null;
  }
  
  // Release explicitly declared objects in hierarchical order.
  System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
  System.Runtime.InteropServices.Marshal.ReleaseComObject(excel);
  
  book = null;
  excel = null;
  
  // As taken from:
  //   http://msdn.microsoft.com/en-us/library/aa679807(v=office.11).aspx.
  System.GC.Collect();
  System.GC.WaitForPendingFinalizers();
  System.GC.Collect();
  System.GC.WaitForPendingFinalizers();
  </code></pre>
  
  <p>All exception handling has been stripped to make the code clearer for this question.</p>
  
  <p>What happens to the <code>[sheet]</code> object in the <code>[foreach]</code> loop? Presumably, it will not get cleaned up, nor can we tamper with it while it is being enumerated. One alternative would be to use an indexing loop but that makes for ugly code and some constructs in the Office Object Libraries do not even support indexing.</p>
  
  <p>Also, the <code>[foreach]</code> loop references the collection <code>[book.Sheets]</code>. Does that leave orphaned RCW counts as well?</p>
  
  <p>So two questions here:</p>
  
  <ul>
  <li>What is the best approach to clean up when enumerating is necessary?</li>
  <li>What happens to the intermediate objects like <code>[Sheets]</code> in <code>[book.Sheets]</code> since they are not explicitly declared or cleaned up?</li>
  </ul>
  
  <p><strong>UPDATE:</strong> </p>
  
  <p>I was surprised by Hans Passant's suggestion and felt it necessary to provide some context.</p>
  
  <p>This is client/server application where the client connects to many different Office apps including Access, Excel, Outlook, PowerPoint and Word among others. It has over 1,500 classes (and growing) that test for certain tasks being performed by end-users as well as simulate them in training mode. It is used to train and test students for Office proficiency in academic environments. With multiple developers and loads of classes, it has been a difficult to enforce COM-friendly coding practices. I eventually resorted to create automated tests using a combination of reflection and source code parsing to ensure the integrity of these classes at a pre-code-review stage.</p>
  
  <p>Will give Hans' suggestion a try and revert back.</p>