写点什么

C#的未来:闭包注解

2015 年 5 月 08 日

在“有一定兴趣”列表上的下一条提议是相当有争议的,这条关于 Lambda 捕获列表的提议假设,它能够对闭包中的变量捕获提供更多的控制能力。

这条提议一上来就讲到了捕获列表,这是一种常见于 C++ 中的概念。以下的示例中包含了一个常见的闭包,以及一个用捕获列表所描述的闭包:

var x = 100;
Func<int> a = () => x * 2;
Func<int> b = [x] () => x * 2;

一旦使用这种语法,那么任何一个没有出现在捕获列表(由中括号 [x] 表示)中的变量都无法在匿名方法中使用,否则将会产生一个编译错误。如果你在这里使用了一个空的列表 [],那么将不会创建任何闭包。这种做法对性能来说有好处,因为不产生闭包的匿名函数将无需进行内存分配。

如果要在闭包中访问当前对象,需要通过使用 [this] 关键字,这种方式也能够减少在无意中捕获当前对象的可能性,因为这会导致内存的泄漏。

按值捕获

有些情况下,你在闭包中只需要使用某个值的拷贝,而并不想让它与原始值共享同一个变量。在这条提议中, 你可以通过以下方式使用捕获列表来表现这一行为。

Func c = int xCopy = x => xCopy * 2;

这种语法非常冗长,因此在提议中也提出了以下几种替代方式,它们的含义是完全相同的。

Func d = value x => x * 2; //this x is a copy
Func e = val x => x * 2; //this x is a copy
Func f = let x => x * 2; //this x is a copy
Func g = =x => x * 2; //this x is a copy

提议中还建议使用以下语法,让常见的按引用捕获的闭包更为明确:

Func h = ref x => x * 2; //x is an alias(别名)
Func i = &x => x * 2; //x is an alias

与之相关的一个提议是使用“细箭头”(使用单横线代替等号),它将隐式地按值捕获所有变量。

Func j = () -> x * 2; //this x is a copy

弱引用捕获

正如之前所述,由于闭包的生命周期比创建它的函数更长,因此它是一种造成内存泄漏的常见原因。因此 Miguel do Icaza 建议在这条提议中加入弱引用的使用,Stephen Toub 对此提出了以下语法:

Action k = [weak myObject] () => […]
Action l = [weak this] () => […]
Action m = [wro = new WeakReference(myObject)] () => […]

批评意见

正如在介绍中所说,这条提议是富有争议的。无论你选择了哪种变种形式,新的语法都会让代码显得相当杂乱。而且对于简短的闭包来说,语法中所包含的信息很可能你早就从代码本身看出来了。

为了支持向后兼容,捕获列表的使用必须是可选的。而由于它的语法实在是非常冗长乏味,所以大多数开发者很可能不愿意使用它,那么这个特性存在的意义就令人怀疑了。

查看英文原文: C# Futures: Closure Annotations

2015 年 5 月 08 日 02:401721
用户头像

发布了 428 篇内容, 共 149.6 次阅读, 收获喜欢 20 次。

关注

评论

发布
暂无评论
  • 小议 Java 语言

    很多新人入门会要求我推荐编程语言,Java 属于我推荐的语言之一,因为 Java 标准、规范,是面向对象编程的代表,在学习其他编程语言的时候还可以参考互通。

    2018 年 1 月 12 日

  • C# 8 小特性

    对于C# 8,有吸引了大多数注意力的重大特性,如默认接口方法和可空引用,也有许多小特性被考虑在内。本文将介绍几例可能加入C#未来版本的小特性。

  • 易用性改进 I:自动类型推断和初始化

    这一讲介绍现代 C++ 引入的几个易用性改进:自动类型推断,初始化列表,及类数据成员的默认初始化。

    2019 年 12 月 13 日

  • Java 深度历险(五)——Java 泛型

    开发人员在使用泛型的时候,很容易根据自己的直觉而犯一些错误。比如一个方法如果接收List<Object>作为形式参数,那么如果尝试将一个List<String>的对象作为实际参数传进去,却发现无法通过编译。虽然从直觉上来说,Object是String的父类,这种类型转换应该是合理的。但是实际上这会产生隐含的类型转换问题,因此编译器直接就禁止这样的行为。本文试图对Java泛型做一个概括性的说明。

  • 异常处理都有哪些陷阱?

    上一讲中我们聊了聊怎么用好Java注解,今天我们谈谈怎么处理异常。

    2019 年 1 月 25 日

  • 浅谈 Java 8 的函数式编程

    Java 8为Java带来了函数式编程。Ben Evans在本文中讨论了函数的意义。通过回顾Java的演变,特别是它的类型系统,我们将看到Java 8的新特性,特别是Lambda表达式带来的改变,并提供函数式编程风格的主要优势。

  • C#的未来:元组及匿名结构体

    随着C# 6接近完成,C# 7的开发计划也开始提到了日程上。虽然目前为止,还没有任何可确定的内容,但C#团队已经开始按照“兴趣及预计可行性”将各种提议进行分类。在这个系列文章中,我们将对某些提议进行分析,首先从对元组的语言支持开始。

  • JEP 286 提议在 Java 局部变量中引入类型推断

    介绍JEP 286的提议已经发送到JEP讨论平台(platform-jep-discuss)邮件列表中,如果能够实现,将在Java局部变量中引入类型推断。由于这只是一个初期阶段的提议,因此并没有计划在Java哪个版本中实现,甚至可能不会实现。

  • 深入浅出 ES6(十三):类 Class

    CMAScript 6已经正式发布了,作为它最重要的方言,Javascript也即将迎来语法上的重大变革,InfoQ特开设“深入浅出ES6”专栏,来看一下ES6将给我们带来哪些新内容。本专栏文章来自Mozilla Web开发者博客,由作者授权翻译并发布。

  • 加餐 | 部分课后思考题答案合集

    希望能对你有所帮助!

    2020 年 2 月 12 日

  • PHP 7 入门:数组、运算符、常量及异常处理的改进

    这是介绍PHP 7.x新特性系列文章的最后一篇,在本文中,我们将讨论其对数组、运算符、常量和异常处理的改进。

  • Practical Go

    演讲嘉宾David Cheney,Heptio 资深工程师, 著名Go语言专家内容介绍Go is a language designed for engineering teams. It’s central themes are simplicity, readability, and maintainability. This talk will provide best practice real world advice for teams building projects in Go covering five areas; idiomatic code, package and api design, error handling, concurrency, and testing.内容大纲Identifiers Choose identifiers for clarity, not brevity Use a consistent declaraton style Package Design A good package starts with its name An identifier’s name includes its package name Prefer lower case package names and import paths Rather than nesting deeply, return early Make the zero value useful Eschew package level state. No package level variables. Avoid global side effects. Project Structure Consider fewer, larger packages Arrange code into files by import statements. Prefer nouns for file names. Eschew elaborate package hierarchies, resist the desire to apply taxonomy Keep package main small as small as possible API Design Design APIs that are hard to misuse. Design APIs for their default use case. Prefer var args to []T parameters Let callers define the interface they require Prefer streaming interfaces Use type assertions for optional behaviour Error handling Elminate handling by eliminating errors Only handle an error once Concurrency Never start a goroutine without when it will stop. When sending or receiving on a channel, consider what happens if the other party never receives the message Keep yourself busy while waiting for a goroutine. or, do the work yourself. Leave concurrency to the caller

    2018 年 12 月 18 日

  • C# 8 的新提案:new 关键字类型推断

    如果目标类型“new”表达式提案被采用,那么就不再需要这些样板代码。

  • JavaScript ES2021 最值得期待的新特性解析

    ES2021又将会发布哪些令人兴奋的新特性呢?

  • 为什么我更喜欢函数式编程

    一个命令式开发人员如何转变成了一个Haskell开发者?

  • Lambda 开发群组意见收集:​“Strawman”语法临时方案

    在Lambda开发邮件列表中,Lambda语法引发了新一轮的讨论,与以往不同的是,这次以收集意见为主。如果您感兴趣,欢迎投上您的一票。​

  • 带你快速上手 Lua

    下面,我带你来快速熟悉下 Lua 的数据类型和语法。

    2019 年 6 月 10 日

发现更多内容

架构师训练营第六周总结

月殇

极客大学架构师训练营

架构师训练营第六周作业

郎哲158

极客大学架构师训练营

架构师训练营第 1 期 -Week6 - 课后练习

鲁小鲁

极客大学架构师训练营

架构师训练营—第五周学习总结

Geek_shu1988

架构师训练营第二周作业

张小胖

极客大学架构师训练营

架构师训练营第二期 Week 2 总结

bigxiang

第六周作业

TheSRE

极客大学架构师训练营

架构师训练营第六周作业

月殇

极客大学架构师训练营

架构师训练营 Week6 - 技术选型 - 分布式数据库,NoSQL,Zookeeper,搜索引擎

极客大学架构师训练营

架构师训练营第 2 期 第二周作业 1

月下独酌

架构师训练营 第六周学习总结

郎哲158

极客大学架构师训练营

第六周作业

Geek_ac4080

技术选型二第六周作业「架构师训练营第 1 期」

天天向善

架构一期第六周作业

Airs

week06学习总结

追风

架构师一期

架构师训练营第六周课程笔记及心得

Airs

分布式CAP原理

Jacky.Chen

架构师训练营 - 第 6周课后作业-CAP原理

树森

架构师训练营—第六周学习总结

Geek_shu1988

第六周总结

Geek_ac4080

架构师训练营—第六周作业

Geek_shu1988

WK1作业

Gavin_From_Mars

第六周-CAP原则理解

袭望

架构师训练营 week2 学习总结

花果山

极客大学架构师训练营

第六周作业 (作业一)

Geek_83908e

极客大学架构师训练营

Week2 框架设计

贺志鹏

极客大学架构师训练营

doris临时故障恢复图

happy

技术选型(1) 课后作业

ABS

架构师训练营—第五周作业

Geek_shu1988

第二周课后练习

jizhi7

极客大学架构师训练营

架构师训练营第 1 期 -Week6 - 技术选型二学习总结

鲁小鲁

极客大学架构师训练营

C#的未来:闭包注解-InfoQ