Почему этот метод получения генерирует исключение StackOverflowException, но только при вызове из одного проекта? - PullRequest
3 голосов
/ 08 февраля 2010

У меня есть несколько проектов:

  • Проект интерфейса базы данных, который определяет Thingo (основное решение)
  • Логический проект, который определяет ThingoChooser (решение для плагина)
  • Проект с графическим интерфейсом, который ссылается на логический проект (решение для плагина
  • Тестовый проект, который ссылается на логический проект (плагин-решение)

Я отлаживаю плагин, поэтому запускаю основное решение с его текущим рабочим каталогом, установленным в каталог bin\Debug, предназначенный для всех проектов плагина. Основной исполняемый файл находит класс плагина в сборке GUI и отображает его основную форму.

В тестовом проекте этот код работает нормально:

this.chooser = new ThingoChooser();
foreach (var thingo in this.chooser.AvailableThingos) {
    Console.WriteLine(release);
}

Тот же код, опубликованный в моем проекте с графическим интерфейсом, завершается с ошибкой StackOverFlowException, когда возвращается AvailableThingos.

ThingoChooser.AvailableThingos выглядит так:

    public IEnumerable<Thingo> AvailableThingos {
        get {
            // Yes, it DEFINITELY case-matches the private variable,
            // NOT the public property. Oh, I wish this were that easy!
            return this.availableThingos;
        }

        private set {
            // ...
        }
    }

… а на какой IEnumerable<Thingo> мне установить this.availableThingos?

Это List<Thingo>.

Да, у меня есть приложение WinForms, которое выдает StackOverFlowException при попытке пройти List<T>. :)

VS2008 совершенно рад разрешить мне проверить this.availableThingos до его возвращения. Когда я нажимаю кнопку шага: StackOverflowException, каждый раз. Это также происходит вне отладчика.

Прекрасные волны мертвой курицы, которые я пробовал, большинство предложено комментаторами, включали:

  • Просмотр трассировки стека для циклов
  • Изменение типа возврата AvailableThingos на List<Thingo>
  • Удаление var в случае, если неявная печать набивала меня
  • Задание переменной резервного хранилища свойства public и прямое обращение к нему
  • Изменение резервного хранилища на List<T>
  • Удаление LINQBridge и перенацеливание на .NET 3.5

Изменения не помогают, и трассировка стека не показывает никаких петель. После одного нажатия кнопки «Step Into» после } метода получения я получаю всплывающее предупреждение с предупреждением об исключении:

Исключение StackOverflowException было обработано

Произошло необработанное исключение типа «System.StackOverflowException» в mscorlib.dll

Ошибка наиболее заметна, когда я переключаюсь на .NET 3.5 и , полностью удаляя LINQBridge и , меняя тип резервного хранилища на List<Thingo> и прямой доступ к нему и просто попробуйте это из кода WinForms:

List<Thingo> thingos = this.chooser.availableThingos.ToList();

Да: вызов .ToList() на List<Thingo> может взорваться с StackOverflowException.

1 Ответ

0 голосов
/ 09 февраля 2010

Проблема оказалась с Копировать локальные настройки в ссылках.

Ссылка проекта GUI на проект интерфейса базы данных имеет параметр Копировать локальный True. Ссылка на логический проект имела набор «Копировать локально» False. Я подозреваю, что логический проект возвращал перечисление Thingo из другой библиотеки DLL, чем проект GUI видел.

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

В тестовом проекте для обоих проектов было установлено значение «Копировать локально» True. Либо совпадение помогло, либо тот факт, что в текущем рабочем каталоге или в пути была только одна копия DLL интерфейса базы данных.

Я с радостью приму лучший ответ, описывающий почему это вызвало StackOverflowException. Я бы сильно предпочел DuplicateCopiesOfAssemblyYouDoofusException.

Для справки, вот карта ссылок и их локальных настроек копирования:

Основной командный проект (запускается под отладчиком, динамически загружает проект с графическим интерфейсом из его каталога bin\Debug):

  • Содержит DLL интерфейса базы данных в том же каталоге, что и основной исполняемый файл. Это тот же каталог, что и все ссылки на интерфейсы базы данных ниже целевого в их пути подсказки.

Проект с графическим интерфейсом (сбой конфигурации):

  • ref → Проект базы данных: Копировать локальный = True
  • ref → Логический проект: Копировать локальный = False

Логический проект:

  • ref → База данных проекта: Копировать локально = False

Тестовый проект:

  • ref → Логический проект: Копировать локальный = True
  • ref → База данных проекта: Копировать локально = True

Честно говоря, комментаторам я не описывал схему решения в вопросе до пяти минут назад, поэтому не могу ожидать, что они ее решат.

...