C# 3.0 中匿名方法的闭包
为什么匿名方法存在闭包? 为什么不直接将状态传递到方法中,而不需要通过复制闭包变量来生成新类的开销? 这难道不是“让一切全球化”的倒退吗?
有人批评我,我觉得我在这里错过了一些东西......
Why do closures exist for anonymous methods? Why not just pass state into the method without the overhead of a new class being generated with the closure variables being copied in? Isn't this just a throwback to "making everything global?"
Someone talk me down, I feel like i'm missing something here...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
有些方法需要特定的签名。 例如:
完全关闭可以非常巧妙地解决这个问题。 您真的不想弄乱匿名方法签名。
Some methods require a specific signature. For example:
A full closure solves this very neatly. You really don't want to mess with the anonymous methods signature.
因为 CLR 会处理它,所以“将状态传递到方法中”的最简单方法是自动生成一个封装该状态的类。
Because the CLR takes care of it, the easiest way to "pass state into the method" is to auto-generate a class, which encapsulates that state.
纯粹是为了方便......您不知道在定义时需要多少状态,例如,一个
Predicate
- 考虑:这里我们传递了两个额外的状态位到
Predicate
(min
和max
) - 但我们无法定义List.FindAll(Predicate<;) T>)
了解这一点,因为这是呼叫者详细信息。另一种方法是自己编写类,但这很困难,即使我们很懒:
我不了解你,但我更喜欢带有闭包的版本......特别是当你考虑到当你有多个上下文级别。 我希望编译器担心它。
还要考虑一下您使用此类构造的频率,尤其是对于 LINQ 之类的东西:您不想以任何其他方式执行此操作...
Purely, convenience... you don't know how much state you are going to need when defining, for example, a
Predicate<T>
- consider:here we've passed two additional bits of state into
Predicate<T>
(min
andmax
) - but we can't defineList<T>.FindAll(Predicate<T>)
to know about that, as that is a caller detail.The alternative is to write the classes ourselves, but that is hard, even if we are lazy:
I don't know about you, but I prefer the version with the closure... especially when you consider how complex it gets when you have multiple contextual levels. I want the compiler to worry about it.
Consider also how often you use such constructs, especially for things like LINQ: you wouldn't want to have to do it any other way...
创建新类的开销可能不需要担心。 这只是 CLR 使绑定变量(由闭包捕获的变量)在堆上可用的便捷方法。 它们仍然只能在闭包范围内访问,因此它们根本不是传统意义上的“全局”。
我相信它们存在的原因主要是为了程序员的方便。 事实上,就我而言,这纯粹是这样。 在 C# 中存在之前,您可以很好地模拟闭包的行为,但您无法获得 C# 3.0 提供的任何简单性和语法糖。 关于闭包的全部要点是,您不需要将父作用域中的变量传递给函数,因为它们是自动绑定的。 实际上,如果您认为替代方案是真正的全局变量,那么程序员使用它会更容易、更清晰。
The overhead of creating a new class probably isn't something to worry about. It's just a convenient way for the CLR to make bound variables (those captured by the closure) available on the heap. They are still only accessible within the scope of the closure, so they're at all not "global" in the traditional sense.
I believe the reason for their existence is mainly convenience for the programmer. In fact, it's purely that as far as I'm concerned. You could emulate the behaviour of a closure pretty well before they existed in C#, but you don't get any of the simplicity and syntactical sugar that C# 3.0 offers. The entire point about closures is that you don't need to pass the variables in the parent scope to the function, because they're automatically bound. It's much easier and cleaner for the programer to work with, really, if you consider that the alternative is true global variables.
至少有一种想法是闭包存在于其他语言中,例如 javascript。 因此,它们可能包含闭包,以符合人们之前使用匿名方法的经验。
At least one thought is that closures exist in other languages such as javascript. So they probably included closures to be in line with people's prior experience with anonymous methods.
因为你写这个:
并且很容易把它变成这个
Because you take write this:
And easily turn it into this