简体   繁体   English

如何避免C#中的StackOverflowException?

[英]How can I avoid a StackOverflowException in C#?

I'm fairly new to C# and thought I'd start with the tutorials here. 我对C#相当陌生,并认为我将从这里的教程开始。

I have done the first 3, and was researching more about C# classes and the various ways you can use them. 我已经完成了前3个,并且正在研究有关C#类以及使用它们的各种方式的更多信息。 It then dawned on me that all my code was in one class (MainForm, as I'm using SharpDevelop) and I should try and organise it better. 然后我发现我所有的代码都在一个类中(MainForm,因为我正在使用SharpDevelop),我应该尝试更好地组织它。 However, when I try to refer to code in other classes, I get a StackOverflowException. 但是,当我尝试引用其他类中的代码时,出现了StackOverflowException。 I have instantiated the class (eg CheckAnswers checkanswers = new checkanswers; ), what's going wrong? 我已经实例化了该类(例如CheckAnswers checkanswers = new checkanswers; ),怎么了? I can post the code if need be, but my guess is that this is some n00b error that is fairly easy to diagnose. 我可以根据需要发布代码,但是我猜这是一些n00b错误,相当容易诊断。

EDIT: 编辑:

Code - https://docs.google.com/open?id=0B9vVcIham8NHMGlNaDk3MTZ6ejA 代码-https: //docs.google.com/open?id=0B9vVcIham8NHMGlNaDk3MTZ6ejA

There's quite a bit. 有很多。 This is only the code that I've written myself, not the form config stuff. 这只是我自己编写的代码,而不是表单配置文件。

You're making mutual-recursion here. 您正在这里进行相互递归。

In MainForm you implicitly call the CheckAnswers constructor at line 23 (it's an initialization of a non-static variable, meaning it'll run when MainForm is constructed). 在MainForm中,您在第23行隐式调用CheckAnswers构造函数(它是非静态变量的初始化,这意味着它将在构造MainForm时运行)。
In CheckAnswers you create a MainForm instance in a similar way (line 193). 在CheckAnswers中,您以类似的方式创建MainForm实例(第193行)。

That'll cause a stack overflow - MainForm creates a CheckAnswers object which Creates a MainForm object which creates a CheckAnswers object which... 这会导致堆栈溢出-MainForm创建一个CheckAnswers对象,该对象创建一个MainForm对象,该MainForm对象创建一个CheckAnswers对象,...

Edit: If you need to make two way communication between the classes (which I advice against in most cases), this won't work. 编辑:如果您需要在类之间进行双向通信(我建议在大多数情况下不建议这样做),则此方法将无效。 The CheckAnswers object hold a reference to a different instance MainForm, an so does the instance of MainForm. CheckAnswers对象持有对另一个实例 MainForm的引用,MainForm实例也是如此。 This will simply not work (as well as cause an infinite recursion as see). 这将根本行不通(并导致无限递归,请参见)。
One way to do what you want is to send an instance of MainForm to the CheckAnswers constructor, and in line 23 use "this" as the parameter for the constructor and initialize mainform (in CheckAnswers) using that parameter. 一种执行所需操作的方法是将MainForm的实例发送到CheckAnswers构造函数,并在第23行中将“ this”用作构造函数的参数,并使用该参数初始化mainform(在CheckAnswers中)。 Something like this: 像这样:

public partial class MainForm : Form
{
    CheckAnswers checkanswers;
    ...
    public MainForm()
    {
        checkanswers = new CheckAnswers(this);
        ...
    }
}
public class CheckAnswers // Not sure why you inherit MainForm here, but it's not a good idea, as someone already stated
{
    MainForm mainform;

    public CheckAnswers (MainForm main)
    {
        mainform = main;
    }
    ...
}

CheckAnswers class derives from MainForm class. CheckAnswers类派生自MainForm类。 So when you call to constructor of CheckAnswers class, it creates instance of this class with all internal members of base class (MainForm). 因此,当您调用CheckAnswers类的构造函数时,它将创建具有基类(MainForm)的所有内部成员的此类的实例。 That's why this line of code is called again: 这就是为什么再次调用此代码行的原因:

Line 23: CheckAnswers checkanswers = new CheckAnswers(); 第23行:CheckAnswers checkanswers = new CheckAnswers();

And again, instance is created and this line of code is called again and again recursively until StackOverflow exception occurs. 再次创建实例,并反复递归调用此行代码,直到发生StackOverflow异常。

Basically, this code represents the same problem as in your code: 基本上,此代码代表与您的代码相同的问题:

class BaseClass
{
    DerivedClass myObject = new DerivedClass(); // this is a recursive call
}

class DerivedClass : BaseClass
{   
}

To communicate, you should pass as parameter an instance of existing object, not create a new one each time (otherwise there will no be communication between the concrete objects). 为了进行通信,您应该将现有对象的实例作为参数传递,而不是每次都创建一个新实例(否则,具体对象之间将没有通信)。

So here is an example that represents the idea of what you need to do instead: 因此,下面的示例代表您需要做什么的想法:

public class CheckAnswers
{
    MainForm mainform;
    public CheckAnswers (MainForm  form)
    { 
        this.mainform = form;
    }

   ...
}

In the MainForm class you will have to pass "itself" as parameter to constructor of CheckAnswers like this: 在MainForm类中,您必须将“自身”作为参数传递给CheckAnswers的构造函数,如下所示:

CheckAnswers checkanswers = new CheckAnswers(this);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM