Анонимное определение класса пространства имен

Excel не выходит, потому что Ваше приложение все еще содержит ссылки на COM-объекты.

я предполагаю, что Вы вызываете по крайней мере одного члена COM-объекта, не присваивая его переменной.

Для меня это было excelApp. Рабочие листы объект, который я непосредственно использовал, не присваивая его переменной:

Worksheet sheet = excelApp.Worksheets.Open(...);
...
Marshal.ReleaseComObject(sheet);

я не знал, что внутренне C# создал обертку для эти Рабочие листы COM-объект, который не стал выпущенным моим кодом (потому что я не знал о нем), и была причина, почему Excel не был разгружен.

я нашел решение своей проблемы на эта страница , которая также имеет хорошее правило для использования COM-объектов в C#:

Никогда использование две точки с COM-объектами.

Так с этим знанием правильный способ сделать вышеупомянутое:

Worksheets sheets = excelApp.Worksheets; // <-- The important part
Worksheet sheet = sheets.Open(...);
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);

ОБНОВЛЕНИЕ ПОСЛЕ СМЕРТИ:

я хочу, чтобы каждый читатель прочитал этот ответ Hans Passant очень тщательно, поскольку он объясняет прерывание I, и много других разработчиков споткнулось в. Когда я записал этот ответ несколько лет назад, я не знал об эффекте, который отладчик имеет к сборщику "мусора" и сделал неправильные выводы. Я сохраняю свой ответ неизменным ради истории, но прочитайте эту ссылку, и не делают , идут путем "двух точек": сборка "мусора" Понимания в.NET и Очищают Excel Interop Objects with IDisposable

10
задан 18 July 2009 в 16:08
поделиться

4 ответа

An anonymous namespace is like the static keyword when it is applied at the global level.

An anonymous namespace makes it so you can't call anything inside the namespace from another file.

Anonymous namespaces allow you to limit the scope of what's within to the current file only.

The programmer would have done this to avoid naming conflicts. No global names will conflict in this way at linking time.

Example:

File: test.cpp

namespace 
{
  void A()
  {
  }
  void B()
  {
  }
  void C()
  {
  }
}

void CallABC()
{ 
  A();
  B();
  C();
}

File: main.cpp

void CallABC();//You can use ABC from this file but not A, B and C

void A()
{
//Do something different
}

int main(int argc, char** argv)
{
  CallABC();
  A();//<--- calls the local file's A() not the other file. 
  return 0;
}

The above will compile fine. But if you tried to write an CallABC() function in your main you would have a linking error.

In this way you can't call A(), B() and C() functions individually, but you can call CallABC() that will call all of them one after the other.

You can forward declare CallABC() inside your main.cpp and call it. But you can't forward declare test.cpp's A(), B() nor C() inside your main.cpp as you will have a linking error.

As for why there is a class inside the namespace. It is to make sure no external files use this class. Something inside the .cpp probably uses that class.

6
ответ дан 4 December 2019 в 01:57
поделиться

If someone links this code and has the definition of an identical named class included and this file is linked before the other implementation you would have a name conflict.

1
ответ дан 4 December 2019 в 01:57
поделиться

В стандарте C ++ ISO (раздел 2.3) вы найдете правило под названием The One Definition Rule .

Из-за сложной взаимосвязи в C ++ между компиляцией и связывание, это не очень простое правило. Большинство деталей здесь .

Но это применимо к функциям, которые являются членами класса, потому что они (на уровне связывания) просто функции с длинными именами.

Это применимо в немного другой способ по сравнению с шаблонами, потому что компоновщик с радостью отбросит лишние определения классов или функций шаблона, которые появляются в отдельных единицах перевода (исходных файлах). Это означает, что если вы предоставите два разных определения одного и того же шаблона, ваша программа будет иметь неопределенное поведение (в лучшем случае: одно из определений будет выбрано молча, случайным образом).

1
ответ дан 4 December 2019 в 01:57
поделиться

У меня создалось впечатление, что у вас могут быть классы с одинаковыми именами в разных единицах перевода без каких-либо конфликтов имен при условии, что у вас нет объявления глобального класса

Ну, это не тот случай. Помните, что эти «общие» определения глобальных классов находятся в файлах заголовков. Они буквально включены, копируя определение общего глобального класса для всех единиц перевода. Если вы используете другой способ включения точно тех же определений классов в несколько единиц перевода (например, расширение макроса), это тоже нормально. Но если у вас есть разные определения для одного и того же класса, вы рискуете неопределенным поведением. Если повезет, ссылка не удастся.

1
ответ дан 4 December 2019 в 01:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: