我们很高兴地宣布对Visual Studio 16.10的F#工具的更新。在这个版本中,我们将继续改善Visual Studio中的F#体验,以去年2月VS 16.9更新中发布的内容为基础。
- 支持Go对外部符号的定义
- 更好地支持在一个解决方案中混合使用C#和F#项目
- 更多的快速修复和重构
- 更多工具性能和响应性的改进
- 更多核心编译器的改进
让我们深入了解一下
转到外部符号的定义
这个功能已经准备了很久了。我们从2016年开始就有一个功能请求,并在这些年里进行了几次试验性实现。现在它来了
如视频中所示,你可以使用f12 键或ctrl+click 来导航到一个声明,就像在你自己的解决方案中的源代码一样。
当你导航时,Visual Studio会生成一个完整的F#签名文件,代表该符号所在的模块或命名空间,如果有XML文档的话。这允许着色、工具提示和进一步的导航工作,就像它们在你自己的代码库中被声明为签名文件一样。
在你的解决方案中更好地混合C#和F#项目
当在同一个代码库中使用C#和F#项目进行互操作时,最大的烦恼之一是,如果其他项目跨越C#<->F#的边界,你需要重建项目以看到其他项目的更新。
从VS 16.10版本开始,如果你对一个C#项目做了修改,你不需要重建它就可以看到F#项目中的变化了
正如视频中所示,我可以做任何修改,并立即看到F#项目中的变化。
今天,反之亦然,从工具的角度来看,要使C# <-> F#的互操作边界变得干净,还有很多工作要做。为了总结事情的现状,这里有一个检查表。
- F#项目可以 "看到 "C#项目中的变化,而无需重建
- 你可以从F#的任何C#符号上转到定义,并导航到C#代码库中的那个点。
- 在不重建的情况下,C#项目不能 "看到 "F#项目中的变化
- 你不能从C#中的任何F#符号上转到定义,并导航到F#代码库中的那个位置。
我们正在做更多的工作,以将剩余的交叉点变成绿色复选标记。这项工作是相当低级的,从对F#编译器的一些改变开始,也可能涉及到对C#工具的改变。
XML文档脚手架
在Visual Studio 2019开始时,由于性能问题,我们禁用了一个允许你在源码中建立XML文档支架的功能。我们发现该实现是UI延迟的一个重要来源,这可能不利于整个Visual Studio的体验,特别是如果与大量的内存消耗相结合。
在Visual Studio 2019的跨度中,我们在F#工具的性能方面取得了很大的进步,包括改变XML文档脚手架功能的实现,使其不再影响UI延迟。所以它现在重新启用了!
你可以通过在结构体顶部的三斜线注释中键入< 字符来触发它,就像下面的视频将演示的那样。
更多快速修复和重构
和上一个版本一样,我们为VS 16.10版本带来了更多的快速修复和重构功能!
删除未使用的绑定快速修复
如果你在任何范围内有一个未使用的绑定,如果它被认为是可移除的,我们会提供给你移除它。

使用适当的不等式运算符快速修复
一些来自其他语言的初学者可能会使用!= ,并被它产生的错误所迷惑。这个快速修复将纠正他们的运算符用法,使用<> 。

为不确定类型的对象添加类型注解快速修复方法
F#编译器可能会给出一个令人困惑的错误,即代码在技术上无法编译,但F#工具实际上可以推断出一个编译器无法推断的类型。这个快速修复将把那个已知的类型带入建议。

添加类型注解重构
最后,我们在Visual Studio的F#工具中添加了第一个重构。重构与快速修复不同,因为它们不是由警告或错误触发的。相反,灯泡(旁边没有错误图标)表明,在你的光标位置有一个代码重构可用。

更多的工具性能和响应性
就像过去几个Visual Studio版本一样,我们正在继续提高大型代码库的工具性能和响应性。
减少了内存的使用
我们为大型解决方案的内存使用确定了另一个 "胜利"。当Visual Studio在一个开放的文档中为结构体着色时,这实际上是一个被称为 "分类 "过程的结果。分类过程分两步进行:
- 语法分类
- 语义分类
语法分类可以做一些事情,比如从非关键工作中识别关键词。它是非常轻量级的,因为它不需要对任何东西进行类型检查。你可能会注意到,对于一个非常、非常大的文件来说,关键词在类型被着色之前就已经被着色了。
语义分类是一种昂贵的操作。它所做的事情包括区分类、结构、枚举、方法、属性等等。最终的结果是在文件中进行更细微的着色。然而,由于它通常是语言服务所启动的第一个语义操作,它也会填充缓存。
语义分类所使用的缓存之一是实际的分类信息本身。这种信息曾经被存储在一个大的数组之中。随着时间的推移,这可能会消耗大量的RAM(尤其是当你有大量的大文件打开时)。为了解决这个问题,我们用一个内存映射文件来备份数据,这是我们在Visual Studio的F#工具中为其他几个大型数据存储所采取的方法。这使得F#代码库节省了高达200MB的空间,这取决于在一个Visual Studio会话中打开了多少文件。
更多的IDE功能立即响应
上次发布时,我们在F#语言服务中开始了一些工作,以使对语义信息的请求不再是串行的。作为复习,所涉及的机器将需要语义信息的请求序列化,因为可能存在着类型检查操作会产生下游影响的情况。它使用一个队列来按顺序处理请求。然而,在实践中,这种方法很少有必要。在这个版本中,我们把更多的操作从这个队列中剥离出来。
有了这些变化,你应该注意到,在较大的代码库中,工具功能对你的输入的反应比以前更快,特别是在较大的代码库中。
核心编译器的改进
最后,我们还有一些编译器的改进可以分享
支持项目文件中的WarnOn
在这个版本之前,如果你想为特定的编译器代码引入警告,你必须在项目文件的OtherFlags 属性中使用--warnon:number 。
现在你可以直接使用WarnOn ,并直接传入数字,就像在C#中一样。
支持项目文件中的ApplicationIcon
在这个版本之前,在F#项目文件中设置ApplicationIcon ,不会有任何作用。
现在,你可以在项目文件中设置这个属性,就像在C#中一样。还增加了一个编译器标志,--win32icon 。
更多跨度优化
Jérémie Chassaing实现了一个可爱的优化,用于在一个Span/ReadOnlySpan 。
以下是F#代码:
let sumArray (vs: int ReadOnlySpan) =
let mutable sum = 0
for i in 0 .. vs.Length-1 do
sum <- sum + vs.[i]
sum
现在发出了更干净的IL,删除了一个边界检查,允许运行时更积极地优化该循环。这种优化也适用于for x in xs do 循环。
展望未来
随着这个版本的发布,我们正式转向支持三个倡议:
- 在.NET 6中对F#的巨大支持
- 在.NET Interactive中对F#的巨大支持
- 在Visual Studio 2022中对F#的巨大支持
对于第一个倡议,我们将锁定我们打算很快发布的语言功能。我们这次不打算增加很多语言功能。我们觉得,现在核心编译器的改进和核心工具的改进(F#交互式,Visual Studio)更有价值。.NET 6是一个LTS版本,我们优先考虑现有功能的完整性、性能和可靠性。这并不一定意味着功能冻结。事实上,我们也可能最终发布一两个 "编译器功能",特别是与改善构建时间有关的功能。但这确实意味着,与F# 5相比,新的语言特性集会更小。当我们有一套最终确定的语言变化进入.NET 6时,我们将宣布它和我们将分配给该版本的版本号。
对于第二项举措,我们主要关注的是确保F#代码能够提供很好的输出(纯文本、图表),有很好的工具(智能提示、工具提示),并提供使用广泛的库的良好体验,特别是那些针对数据科学和机器学习的库。为此,我们已经完成了许多我们打算做的事情,特别是在支持一些奇特的软件包布局,以引入具有本地依赖性的不同软件包。但仍有一些工作要做,比如确保工具体验(完成度、工具提示等)都能很好地工作。我们致力于在.NET Interactive在GA发布时提供一个令人难以置信的F#体验。
最后,我们非常专注于确保在Visual Studio 2022中提供良好的F#体验。由于Visual Studio 2022将是64位的,这意味着与现在相比会有更高的内存使用率。我们有大量的性能分析工作要做。我们的初步构建表明,当加载F#代码库并运行像查找所有引用这样的昂贵操作时,内存使用量是2倍。我们致力于尽可能地降低这一因素。除此之外,我们希望继续迭代Visual Studio的生产力功能,并带来诸如Inline Hints、更好的C#互操作、更快的构建时间等功能。
敬请关注,并祝F#编码愉快!