对同一方法的后续方法调用是否会进入新的上下文?

时间:2015-07-03 12:23:09

标签: c#

我有一个关于方法调用和堆栈指针的问题。

基本上我有一个程序可以读取用户的输入。创建类的对象"输入"后,方法调用" prompt()"提供一个包含选项的菜单,您所做的每个选择都会调用一个执行某些操作的新方法。做出选择后,您始终可以选择返回主菜单,此操作会调用" prompt()"再次。

现在,我的问题是,每次调用"提示()"指向内存堆栈中的新位置还是会进入与第一次调用时相同的上下文?即,可以一遍又一遍地回到主菜单来创建内存泄漏吗?

class inOut {

public string[] Prompt(){
   ...
   presentChoices();
   ...
}

private void PresentChoices(){
   ...
   if(someChoice){
       manualInput();
   }
   ...
}

private void ManualInput(){
   ...
   if(goBack){
       Prompt();
   }
   ...
}

}

我希望问题很明确,并提前感谢任何答案!

4 个答案:

答案 0 :(得分:0)

对于您输入的每种方法,都应该有相应的return。否则可能会导致StackOverlow。它不是新的上下文,而是堆栈中剩余的值,用于return返回到调用方法的位置以及方法调用本身(通过参数)。

要拥有重复某些内容,您可以使用无限循环:

while(true)
{
    ... // repeat this action

    if(endcondition)
        break;
}

在您的情况下,重复操作是调用prompt()来显示菜单。它可能具有返回值,无论何时重复或退出,都可以在endcondition中使用。

答案 1 :(得分:0)

只要在同一个对象实例上调用该方法,它就会成为指向同一个地址的指针。

当您创建对象的新实例时,每个对象都有自己的指针。 如果要避免这种情况,则需要将方法定义为静态。在这种情况下,您将不是从实例而是从类型调用该方法。

特别是当您从同一实例上下文中反复调用相同的方法时,需要注意的是递归调用。对于许多递归调用(数千个)将导致StackOverFlowException(如此网站的名称)。您可以在Visual Studio的StackTrace窗格中查看是否有递归调用,或者如果安装了Resharper,它将在文档的左侧告诉您。

无论哪种方式,你在这里描述的并不是真正的“内存泄漏”(ML是未使用的对象,不会被收集并留在内存中没有做任何事情)而是堆栈溢出情况。

答案 2 :(得分:0)

不再引用的对象是垃圾回收。记录Input对象会发生什么。

... Unlesss

......你做错了。

在Winform应用程序中,如果由于某种原因涉及事件处理程序(事件的发布者比订阅者的寿命更长)阻止垃圾回收,通常会发生错误。

答案 3 :(得分:0)

假设您的代码如下所示:

void Prompt()
{
  // ...
  var obj = new Input();
  // ...
  if (someCondition)
  {
    Prompt(); // recursive
  }
  // ...
  // Is 'obj' used here?
}

然后当你递归地调用Prompt()时,是的,创建了一个新的上下文。 obj变量将指向新对象等。

如果递归变得非常非常深,你可能得到一个StackOverflowException(堆栈中没有更多的空间用于新的“调用帧”),或者你可能得到OutOfMemoryException(不再有堆) Input个实例的空间。

但是,如果您因某种原因知道递归不会变得太深,那么垃圾收集器会在安全的情况下为您清理。

但也许您应该考虑使用while(或do)循环,而不是让您的方法自行调用?这实际上取决于你想要达到的目标。

我可能误解了你的问题。可能Prompt()本身不会调用Prompt?你应该给出简化的代码结构(比如我上面的代码示例),以便明确从哪里调用什么。