c# – 模糊编译器的lambda表达式转换
我研究了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 = null; 那么第一个实例就无法收集了.实例无法通过makeAdder访问,但可以通过addFive访问. 在建议的codegen中,首先可以在此场景中收集,因为无法通过addFive访问实例. 你是正确的,在这种特殊情况下,优化是合法的.然而,由于Ben Voigt在他的回答中描述的原因,它一般不合法.如果f在Curry中发生变异,那么local.function必须变异.但是在执行外部委托之前,本地无法访问第二个实例. C#编译器团队可以选择进行您已经确定的优化,但迄今为止的微小节省根本不值得花费. 我们正在考虑让罗斯林按照你所描述的方式进行优化;也就是说,如果已知外部变量不变异,则更积极地捕获其值.我不知道这种优化是否适用于Roslyn. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- XML基础,与HTML的对比中学习
- postgresql 测试库和生产库2个数据库之间在线导数据
- 知道这20个正则表达式,能让你少写1,000行代码
- objective-c – XCode中与null相关的属性属性有什么作用?
- [Flash/Flex] 使用Flash的C++编译器Flascc的提示和窍门
- SQLite的C++类,同时支持ANSI 和UNICODE编码
- ruby-on-rails – 基于现有资源的表单挑战Rails问题
- ruby-on-rails-4 – Material Design Lite不能与Turbolinks
- c# – 一个进程中不同版本的Enterprise Library
- React—Native开发之原生模块向JavaScript发送事件