Должен ли я освобождать объект COM на каждой итерации foreach?

Здесь (потенциальная) проблема:

Я создаю COM-объект, а затем использую "foreach" для повторения каждого элемента в возвращаемой коллекции. Нужно ли мне выпускать каждый отдельный элемент, который я повторяю в коллекции? (См. Код ниже.) Если это так, я не могу придумать, как эффективно его освободить из выражения "finally", на случай, если с ним будет работать ошибка.

Любые предложения?

private static void doStuff()
{
    ComObjectClass manager = null;

    try
    {
        manager = new ComObjectClass();
        foreach (ComObject item in manager.GetCollectionOfItems())
        {
            Log.Debug(item.Name);
            releaseComObject(item); // <-- Do I need this line?
                                    //     It isn't in a 'finally' block...
                                    //             ...Possible memory leak?
        }
    }
    catch (Exception) { }
    finally
    {
        releaseComObject(manager);
    }
}

private static void releaseComObject(object instance)
{
    if (instance != null)
    {
        try
        {
            System.Runtime.InteropServices.Marshal.ReleaseComObject(instance);
        }
        catch
        {
            /* log potential memory leak */
            Log.Debug("Potential memory leak: Unable to release COM object.");
        }
        finally
        {
            instance = null;
        }
    }
}

Ответы

Ответ 1

Вы не должны использовать оператор foreach с объектом COM, поскольку ссылка делается за кулисами, на которые у вас нет контроля над выпуском. Я бы переключился на цикл for и убедитесь, что вы никогда не используете две точки со COM-объектами.

Как бы это выглядело:

try
{
    manager = new ComObjectClass();
    ComObject comObject = null;
    ComObject[] collectionOfComItems = manager.GetCollectionOfItems();
    try
    {
        for(int i = 0; i < collectionOfComItems.Count; i++)
        {
            comObject = collectionOfComItems[i];
            ReleaseComObject(comObject);
        }
    }            
    finally
    {
        ReleaseComObject(comObject);
    }
}
finally 
{
    ReleaseComObject(manager);
}