加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 模糊编译器的lambda表达式转换

发布时间:2020-12-16 02:00:54 所属栏目:百科 来源:网络整理
导读:我研究了Y Combinator(使用c#5.0)并且在这种方法时非常惊讶: public static FuncT1,FuncT2,TOut CurryT1,T2,TOut ( this FuncT1,TOut f){ return a = b = f(a,b);} …由编译器翻译成: public static FuncT1,TOut(this FuncT1,TOut f) { firstT1,TOut local
我研究了Y Combinator(使用c#5.0)并且在这种方法时非常惊讶:

public static  Func<T1,Func<T2,TOut>> Curry<T1,T2,TOut> ( this Func<T1,TOut> f)
{
    return a => b => f(a,b);
}

…由编译器翻译成:

public static Func<T1,TOut>(this Func<T1,TOut> f)
        {
            first<T1,TOut> local = new first<T1,TOut>();
            local.function = f;
            return new Func<T1,TOut>>(local.Curry);
        }
    private sealed class first<T1,TOut>
    {
        private sealed class second
        {
            public first<T1,TOut> ancestor;
            public T1 firstParameter;
            public TOut Curry(T2 secondParameter)
            {
                return ancestor.function(firstParameter,secondParameter);
            }
        }
        public Func<T1,TOut> function;
        public Func<T2,TOut> Curry(T1 firstParameter)
        {
            second local = new second();
            local.ancestor = this;
            local.firstParameter = firstParameter;
            return new Func<T2,TOut>(local.Curry);
        }
    }

因此,当我们使用引用second.Curry的委托时,第二个类是嵌套的并且第一个类不可用于垃圾收集.与此同时,我们在头等舱中所需要的只是功能.也许我们可以将它(委托)复制到第二个类,然后可以收集第一个类?是的,我们也应该做第二类非嵌套但看起来没问题.据我所知,代表是“按价值”复制的,所以我可以建议它很慢,但同时我们复制firstParameter?!所以,可能有人可以解释,为什么编译器会做所有这些事情?)
我说的是这样的:

private sealed class first<T1,TOut>
{
        public Func<T1,TOut> Curry(T1 firstParameter)
        {
            second<T1,TOut> local = new second<T1,TOut>();
            local.function = function;
            local.firstParameter = firstParameter;
            return new Func<T2,TOut>(local.Curry);
        }
    }
    public sealed class second<T1,TOut>
    {
        public T1 firstParameter;
        public Func<T1,TOut> function;
        public TOut Curry(T2 secondParameter)
        {
            return function(firstParameter,secondParameter);
        }
    }

解决方法

这个问题很难理解.让我澄清一下.您的建议是编译器可以生成

public static Func<T1,TOut> f)
{
    first<T1,TOut>();
    local.function = f;
    return new Func<T1,TOut>>(local.Curry);
}
private sealed class first<T1,TOut>
{
    private sealed class second
    {
        //public first<T1,TOut> ancestor;
        public Func<T1,TOut> function;
        public T1 firstParameter;
        public TOut Curry(T2 secondParameter)
        {
            return /*ancestor.*/function(firstParameter,secondParameter);
        }
    }
    // public Func<T1,TOut> function;
    public Func<T2,TOut> Curry(T1 firstParameter)
    {
        second local = new second();
        // local.ancestor = this;
        local.function = function;
        local.firstParameter = firstParameter;
        return new Func<T2,TOut>(local.Curry);
    }
}

是?

您的主张是,由于这种情况,这是一项改进.

Func<int,int,int> adder = (x,y)=>x+y;
Func<int,Func<int,int>> makeAdder = adder.Curry();
Func<int,int> addFive = makeAdder(5);

> addFive是第二个实例上方法的委托
> makeAdder是第一个实例上方法的委托
>在原始的codegen中,第二个持有祖先,这是第一个相同的实例

因此,如果我们说

makeAdder = null;

那么第一个实例就无法收集了.实例无法通过makeAdder访问,但可以通过addFive访问.

在建议的codegen中,首先可以在此场景中收集,因为无法通过addFive访问实例.

你是正确的,在这种特殊情况下,优化是合法的.然而,由于Ben Voigt在他的回答中描述的原因,它一般不合法.如果f在Curry中发生变异,那么local.function必须变异.但是在执行外部委托之前,本地无法访问第二个实例.

C#编译器团队可以选择进行您已经确定的优化,但迄今为止的微小节省根本不值得花费.

我们正在考虑让罗斯林按照你所描述的方式进行优化;也就是说,如果已知外部变量不变异,则更积极地捕获其值.我不知道这种优化是否适用于Roslyn.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读