使用Lambda的递归性的记忆行为

时间:2016-08-21 00:32:57

标签: c# memory lambda closures

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

        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函数本身的定义?

1 个答案:

答案 0 :(得分:1)

示例方法将由编译器翻译成如下:

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个堆分配,加上使用委托调用与使用常规静态递归方法的直接调用。

IMO额外的运行时成本并不是那么大,但同时由于在这种情况下使用递归lambda绝对没有好处,因此最好避免使用。