Title: Iterating on Outlook COM objects
Tags: vsto;outlook-addin;office-interop;office-addins;com-interop
Question: I have a doubt about when iterating over Outlook COM objects and whether I need always to release them or not.
What is the difference between below two for loops?
(suppose recipients is of type Outlook.Recipients)
foreach (Outlook.Recipient recipient in recipients)
// Do things here
// Release Outlook COM object (Is it necessary to release it?)
Marshal.ReleaseComObject(recipient);
for (int i = 1; i <= recipients.Count; i++)
// Do things here
Outlook.Recipient recipient = recipients[i];
// Release Outlook COM object (Is it necessary to release it?)
Marshal.ReleaseComObject(recipient);
And is it necessary to release Outlook.Recipient object in both cases?
I have heard that it is recommended that you rather use a for loop since a for-each might cause some unexpected behavior and your code to hang.
Using a foreach loop to loop through the Recipients collection automatically generates the enumerator behind the foreach statement that uses an internal COM object, which needs to be released.


Here is another answer: There are two main ways for releasing underlying COM objects in .net based applications:
The first one is based on the garbage collector which swipes the heap and could also automatically release hanging objects. But to properly release COM objects you would need to call the GC twice:
GC.Collect
GC.WaitForPendingFinalizers
GC.Collect
GC.WaitForPendingFinalizers
Use the Marshal.ReleaseComObject method in the code to release underlying COM objects instantly in the code. I prefer using this way because it allows releasing objects where they were created and don't wait until GC finishes its work which is un-deterministically.
In that case the foreach loop is not recommended because it doesn't allow releasing COM objects that way. I always use an old approach with the for loop:
for (int i = 1; i <= recipients.Count; i++)
// Do things here
Outlook.Recipient recipient = recipients[i];
// Release Outlook COM object (Is it necessary to release it?)
Marshal.ReleaseComObject(recipient);
recipient = null;
Don't forget to set the source object to null.

Here is another answer: Unless you are running into a specific problem, don't call Marshal.ReleaseComObject().
The first loop checks (at compile time) that the object implements _NewEnum property with the dispid of -4. At run-time, .Net reads that property and casts it to the IEnumVariant interface that is used to loop through the collection items. .Net run-time version of the enumerator tends to keep all accessed items referenced, so Marshal.ReleaseComObject won't have any effect until the loop exits and the enumerator is released.
The second one is just a good old for loop. Marshal.ReleaseComObject would work as expected.
Comment for this answer: And in the first case, first loop, if Marshal.ReleaseComObject won't have any effect until the loop exits and the enumerator is released, where do I have to call Marshal.ReleaseComObject, or is not needed because Outlook object will be released automatically in this case?
Comment for this answer: If you don't call the `Marshal.ReleaseComObject` method in the code underlying COM objects are released (the reference counter is decreased) when GC will be run twice.
Comment for this answer: This limit for the Exchange server was updated and now the number is much higher.
Comment for this answer: All COM objects will be released in .Net apps. The question is when - GC will take care of that at some later point. You need `Marshal.ReleaseComObject()` only if you are running into a specific problem - e.q., you are iterating over items in an online folder and you run into errors caused by having more than 255 RPC channels (one for each open item). If there is no such problem, `Marshal.ReleaseComObject()` is not needed.

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 2, 'CommentCount': 0, 'ContentLicense': 'CC BY-SA 4.0', 'CreationDate': '2022:00:08/09/22', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<vsto><outlook-addin><office-interop><office-addins><com-interop>', 'Title': 'Iterating on Outlook COM objects', 'ViewCount': 39, 'id': 73298306, 'user_AboutMe': '<p>Computer Scientist and Technology Enthusiast</p>\n', 'user_AccountId': 1782106.0, 'user_DisplayName': 'Rodri', 'user_Reputation': 8964.0, 'user_Views': 1682.0, 'user_id': 1624552.0}}