使用Lambda的递归内存行为

本文关键字:内存 递归 Lambda 使用 | 更新日期: 2023-09-27 18:03:12

我正在使用以下代码对二叉树进行预排序遍历:

        public void PreorderTraversal(Action<BinaryTreeNode<T>> act) {
            Action<BinaryTreeNode<T>> InnerTraverse = null;
            InnerTraverse = (node) => {
                if (node == null) return;
                act(node);
                InnerTraverse(node.Left);
                InnerTraverse(node.Right);
            };
            InnerTraverse(this.Root);
        }

从性能角度来看,使用本地定义的lambda在树上重复出现的方法是否比简单地将InnerTraverse函数定义为BinaryTree类上的方法更糟糕,这是定义PreorderTraversal函数本身的地方?

使用Lambda的递归内存行为

这个示例方法将被编译器翻译成这样:

class Closure
{
     public Action<BinaryTreeNode<T>> act;
     public Action<BinaryTreeNode<T>> InnerTraverse;
     public void InnerTraverseFunc(BinaryTreeNode<T> node)
     {
         if (node == null) return;
         this.act(node);
         this.InnerTraverse(node.Left);
         this.InnerTraverse(node.Right);
     }
}
public void PreorderTraversal(Action<BinaryTreeNode<T>> act)
{
    var c = new Closure();
    c.act = act;
    c.InnerTraverse = new Action<BinaryTreeNode<T>>(c.InnerTraverseFunc);
    c.InnerTraverse(this.Root);
}

您可以看到,成本是每个T一个新类型,每个根方法调用2个堆分配加上使用委托调用与使用常规静态递归方法的直接调用。

在我看来,额外的运行时成本并不是很大,但同时由于在这种情况下使用递归lambda绝对没有好处,所以最好避免使用。