Почему этот код заставляет Excel не закрываться должным образом?

Почему эта строка кода приводит к тому, что Excel не выходит?

Excel.Range range = (Excel.Range)ws.Cells[1,1];

Если это из-за кастинга, то не будет ли этот код вызывать ту же проблему?

Excel.Worksheet ws = (Excel.Worksheet)wb.ActiveSheet;

Я пробовал. Но это работает. Excel закроется.

Если я использую этот код. Excel закрывается.

Excel.Range range = ws.get_Range("A1","A1");

И какая разница? Да, я знаю, как миллион строк "Как закрыть Excel правильно". Но поскольку это вопрос, а не ответ, я решил попросить нового, а не спрашивать у других людей вопрос.

Вот мой код. Но, конечно, между ними есть другие коды. Я просто комментирую все и медленно пытаюсь выяснить, какие строки заставляют Excel не закрываться. Я понимаю, что даже без использования сборщика мусора Excel все еще закрывается. Я не хочу использовать кувалду, чтобы закрыть Excel.

Спасибо.

Excel.Application objExcel = new Excel.Application();
Excel.Workbooks wbs = objExcel.Workbooks;
Excel.Workbook wb = wbs.Open(saveFileDialog1.FileName, Type.Missing,  Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Excel.Worksheet ws = (Excel.Worksheet)wb.ActiveSheet;
//Excel.Range range = (Excel.Range)ws.Cells[1,1];
Excel.Range range = ws.get_Range("A1","A1");

FinalReleaseAnyComObject(range);
FinalReleaseAnyComObject(ws);
wb.Close(Type.Missing, Type.Missing, Type.Missing);
FinalReleaseAnyComObject(wb);
FinalReleaseAnyComObject(wbs);
objExcel.Quit();
FinalReleaseAnyComObject(objExcel);

В настоящее время я пробовал до objExcel, wbs, wb и ws. Эти 4 объекта не создают проблем.

private static void FinalReleaseAnyComObject(object o)
{
    Marshal.FinalReleaseComObject(o);
    o = null;
}

Я понимаю, что вы также не можете повторно использовать переменную.

Excel.Range range = ws.get_Range("A1","G1");
range = ws.get_Range("A1", "A1");

Это приведет к тому, что Excel не будет правильно закрываться. Вместо этого используйте это.

Excel.Range range = ws.get_Range("A1","G1");
FinalReleaseAnyComObject(range);
range = ws.get_Range("A1", "A1");

Ответ 1

Там скрытый указатель интерфейса диапазона, который вы не видите, свойство Cells возвращает его. Затем вы применяете к нему выражение индексатора, разыменовывая свойство Item по умолчанию для этого диапазона. Чтобы получить другой диапазон.

Вот почему такая плохая и плохая идея - попытаться самостоятельно управлять указателями интерфейса COM. Доверяйте сборщику мусора, чтобы всегда все было правильно. GC.Collect() и GC.WaitForPendingFinalizers(), если вы действительно хотите действительно прекратить работу по требованию. Обязательно прочитайте этот ответ, чтобы понять, почему это не всегда срабатывает, как ожидается, при отладке вашей программы.