这些变量会被垃圾收集吗?

时间:2016-07-17 19:20:14

标签: c# .net algorithm

我今天正在练习我的编码排序并解决"从链接列表中删除某个值的所有元素"今天的问题。我提出的解决方案是

public void RemoveAll ( T val ) 
{
    if(_root == null)
       return;

    if(_root.Value == val)
    {
       _root = _root.Next;
       RemoveAll(val);
    }    

    Node last = _root, 
          cur = _root.Next;  
    while(cur != null)
    {
       if(cur.Value == val)
           last.Next = cur.Next;
       else
           last = cur;
       cur = cur.Next;
    }
}

以及我的问题:

cur.Value == val我正在执行更改

列表时
A -> B -> C

A -> C

编译器或运行时环境是否会看到B不再使用并将其丢弃?或者我应该明确地这样做吗?

我还有第二个问题,即调用堆栈是否会出现递归void方法。正如您在此处看到的,该方法可能会调用自身。但由于它是一种不返回值的方法,运行时环境是否只能擦除最后一次调用的数据?它没有理由留在内存中(对吧?)。

1 个答案:

答案 0 :(得分:1)

  

编译器或运行时环境是否会看到B已不再使用并将其丢弃?或者我应该明确地这样做吗?

GC,当它运行时,将意识到没有对该对象的活动引用并清理它(假设没有其他人拥有对该对象的引用)。您无法在.NET中手动清理单个对象。在.NET中,内存由垃圾收集器根据需要进行管理和清理。

  

我还有第二个问题,即调用堆栈是否会破坏递归void方法。正如您在此处看到的,该方法可能会调用自身。但由于它是一种不返回值的方法,运行时环境是否只能擦除有关上次调用的数据?它没有理由留在内存中(对吧?)。

您正在描述tail recursion. C#编译器不会生成尾递归调用。如果你的递归太深,那么你可能会遇到StackOverflowException。[/ p>

该限制不是CLR限制 - .NET Framework确实支持尾调用。它是C#编译器,不会发出尾部IL操作码。当手动生成IL或使用F#时,您可以在.NET Framework中使用Tail Recursion,它会在适当的时候生成尾调用。

有关详细信息,请参阅https://stackoverflow.com/a/15865150/1163867

PS。我认为您的代码有错误。看起来你应该在递归调用RemoveAll后提前返回:

if(_root.Value == val)
{
   _root = _root.Next;
   RemoveAll(val);
   return;
}