为什么此 getter 会抛出 StackOverflowException,但仅在从一个项目调用时才抛出?

发布于 2024-08-20 19:53:38 字数 2304 浏览 4 评论 0原文

我有几个项目:

  • 定义 Thingo 的数据库接口项目(主要解决方案)
  • 定义 ThingoChooser 的逻辑项目(插件解决方案)
  • 引用逻辑项目的 GUI 项目(插件解决方案
  • 一个引用逻辑项目(插件解决方案)的测试项目

我正在调试插件,因此我运行主解决方案,并将其当前工作目录设置为目标为 bin\Debug 目录所有插件项目。主可执行文件在 GUI 程序集中找到插件类并显示其主窗体。

在测试项目中,此代码工作正常:

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

发布到我的 GUI 项目中的相同代码失败并出现 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 < code>this.availableThingos?

这是一个 List

是的,我有一个 WinForms 应用程序,它在尝试遍历 List< 时抛出 StackOverFlowException 。 ;T>:)

VS2008 非常乐意让我在返回之前检查 this.availableThingos。当我每次单击步骤按钮时:StackOverflowException。它也发生在调试器之外。

我尝试过的死鸡细浪,大多数评论者建议包括:

  • 查看循环的堆栈跟踪
  • AvailableThingos 的返回类型更改为 List
  • 删除 var 以防隐式类型让我感到困惑
  • 将属性的后备存储变量设置为 public 并直接命中它将
  • 后备存储更改为 List >
  • 删除 LINQBridge 并重新定位到 .NET 3.5

这些更改没有帮助,并且堆栈跟踪没有显示任何循环。单击 getter 的 } 之后的“Step Into”按钮后,我得到了异常警告浮动读数:

StackOverflowException 未处理

mscorlib.dll 中发生“System.StackOverflowException”类型的未处理异常

当我切换到 .NET 3.5 并完全删除 LINQBridge 时,该错误最为严重并且将后备存储的类型更改为 List 并且直接访问它并且只需从WinForms 代码:

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

是的:在 List 上调用 .ToList() 可能会因 StackOverflowException 而崩溃。

I have a few projects:

  • A database interface project that defines Thingo (main solution)
  • A logic project that defines ThingoChooser (plugin solution)
  • A GUI project that refers to the logic project (plugin solution
  • A test project that refers to the logic project (plugin solution)

I'm debugging the plugin, so I run the main solution with its current working directory set to the bin\Debug directory targeted by all of the plugin projects. The main executable finds the plugin class in the GUI assembly and displays its main form.

In the test project, this code works fine:

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

The same code, posted into my GUI project, fails with a StackOverFlowException when AvailableThingos returns.

ThingoChooser.AvailableThingos looks like this:

    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 {
            // ...
        }
    }

… and to what kind of IEnumerable<Thingo> do I set this.availableThingos?

It's a List<Thingo>.

Yes, I have a WinForms app that throws StackOverFlowException when trying to walk a List<T>. :)

VS2008 is perfectly happy to let me inspect this.availableThingos before it's returned. When I click the step button: StackOverflowException, every time. It also happens out of the debugger.

Fine waves of the dead chicken I've tried, most suggested by commenters, included:

  • Looking at the stack trace for loops
  • Changing the return type of AvailableThingos to List<Thingo>
  • Removing var in case implicit typing stuffed me up
  • Making the property's backing store variable public and hitting it directly
  • Changing the backing store to a List<T>
  • Removing LINQBridge and re-targeting to .NET 3.5

The changes don't help, and the stack trace doesn't show any loops. After one click of the “Step Into” button after the } of the getter, I get the exception warning float-over reading:

StackOverflowException was unhandled

An unhandled exception of type 'System.StackOverflowException' occurred in mscorlib.dll

The bug is at its most dramatic when I switch to .NET 3.5 and remove LINQBridge entirely and change the type of the backing store to List<Thingo> and access it directly and simply try this from the WinForms code:

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

Yep: calling .ToList() on a List<Thingo> can blow up with StackOverflowException.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小镇女孩 2024-08-27 19:53:38

问题出在引用上的复制本地设置

GUI 项目对数据库接口项目的引用已将“复制本地”设置为 True。它对逻辑项目的引用已将 Copy Local 设置为 False。我怀疑逻辑项目从与 GUI 项目所看到的不同的 DLL 返回 Thingo 的枚举。

(问题的发生可能是必要的:调试时,我正在运行第五个项目,它动态加载 GUI 项目的 DLL。第五个项目有自己的数据库接口项目 DLL 副本。)

测试项目有 Copy Local对于这两个项目都设置True。要么匹配有帮助,要么只是因为当前工作目录或路径中只有一个数据库接口 DLL 的副本。

我很乐意接受描述为什么这导致StackOverflowException的最佳答案。我强烈推荐 DuplicateCopiesOfAssemblyYouDoofusException

作为参考,这里是引用图及其复制本地设置:

主命令项目(在调试器下运行,从其 bin\Debug 目录动态加载 GUI 项目):

  • 与数据库接口 DLL 位于同一目录中主要可执行文件。该目录与其提示路径中目标下的所有数据库接口引用位于同一目录。

GUI 项目(配置失败):

  • ref→ 数据库项目:Copy Local = True
  • ref→ 逻辑项目:Copy Local = False

逻辑项目:

  • ref→ 数据库项目:Copy Local = False

测试项目:

  • ref→ 逻辑项目:Copy Local = True
  • ref→ 数据库项目:Copy Local = True

平心而论,直到五分钟前我才描述问题中的解决方案布局,所以我不能指望他们解决它。

The problem turned out to be with the Copy Local settings on the references.

The GUI project's reference to the database interface project had Copy Local set True. Its reference to the logic project had Copy Local set False. I suspect the logic project was returning an enumeration of a Thingo from a different DLL than the GUI project was seeing.

(Perhaps necessary for the problem to occur: when debugging, I'm running a fifth project which dynamically loads the DLL for the GUI project. That fifth project has its own copy of the database interface project DLL.)

The test project had Copy Local for both projects set True. Either the match helped, or just the fact that there was only one copy of the database interface DLL in the current working directory or on the path.

I'll happily accept the best answer describing why this caused StackOverflowException. I'd have strongly preferred a DuplicateCopiesOfAssemblyYouDoofusException.

For reference, here's the map of references and their Copy Local settings:

Main command project (run under debugger, dynamically loads GUI project from its bin\Debug directory):

  • Has database interface DLL in same directory as the main executable. This is the same directory as all database interface references below target in their hint path.

GUI project (failing configuration):

  • ref→ Database project: Copy Local = True
  • ref→ Logic project: Copy Local = False

Logic project:

  • ref→ Database project: Copy Local = False

Test project:

  • ref→ Logic project: Copy Local = True
  • ref→ Database project: Copy Local = True

In all fairness to the commenters, I didn't describe the solution layout in the question until five minutes ago, so I can't expect them to have solved it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文