为什么此 getter 会抛出 StackOverflowException,但仅在从一个项目调用时才抛出?
我有几个项目:
- 定义
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
toList<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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题出在引用上的复制本地设置。
GUI 项目对数据库接口项目的引用已将“复制本地”设置为
True
。它对逻辑项目的引用已将 Copy Local 设置为False
。我怀疑逻辑项目从与 GUI 项目所看到的不同的 DLL 返回Thingo
的枚举。(问题的发生可能是必要的:调试时,我正在运行第五个项目,它动态加载 GUI 项目的 DLL。第五个项目有自己的数据库接口项目 DLL 副本。)
测试项目有 Copy Local对于这两个项目都设置
True
。要么匹配有帮助,要么只是因为当前工作目录或路径中只有一个数据库接口 DLL 的副本。我很乐意接受描述为什么这导致
StackOverflowException
的最佳答案。我强烈推荐DuplicateCopiesOfAssemblyYouDoofusException
。作为参考,这里是引用图及其复制本地设置:
主命令项目(在调试器下运行,从其
bin\Debug
目录动态加载 GUI 项目):GUI 项目(配置失败):
True
False
逻辑项目:
False
测试项目:
True
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 setFalse
. I suspect the logic project was returning an enumeration of aThingo
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 aDuplicateCopiesOfAssemblyYouDoofusException
.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):GUI project (failing configuration):
True
False
Logic project:
False
Test project:
True
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.