对于C#的两个重要特性元组和Ref返回值,Visual Basic 15提供了对等的实现。这两个特性都是“不完全的”,但已经可以提供足够的变通方案,让VB应用程序可以消费使用了这些特性的C#库。

元组

在VB中,从单个函数调用直接返回多个值是一个人们期待已久的特性。虽然开发人员可以使用ByRef参数获得同样的结果,但与函数式编程语言相比,其语法相当笨拙。

你可能不熟悉这个术语,“元组”就是一组相关的值。从.NET 4.0开始,Visual Basic就提供了一个标准的Tuple类,但用户体验不那么令人满意。开发人员必须手动解包来获得Tuple的值,而且要使用Item1、Item2等不能提供什么帮助的属性名。

七年之后,VB 15终于为元组提供了语法支持。更确切地说,与堆分配Tuple对象相比,ValueTuple结构提供了更好的性能。下面是一个例子,TryParse方法是使用新的风格编写的:

Public Function TryParse(s As String) As (Boolean, Integer)TryDim numericValue = Integer.Parse(s)Return (True, numericValue)CatchReturn (False, Nothing)End TryEnd Function
Dim result = TryParse(s)If result.Item1 ThenWriteLine(result.Item2)End If

在这个例子中,TryParse的返回值是ValueTuple。这使得函数更简洁了一些,因为你不必再显式说明ValueTuple类型。但是,如你所见,调用它的代码没有任何不同。因此,让我们稍微改进一下,但保持返回类型的字段不变:

Public Function TryParse(s As String) As (IsInteger As Boolean, Value As Integer)…End FunctionDim result = TryParse(s)If result.IsInteger ThenWriteLine(result.Value)End If

你可以使用下面的语法创建带有命名字段的元组:

Dim kvPair = (Key := 5, Value := "Five")

遗憾的是,VB没有提供一种可以将元组“解包”到多个变量的方法。因此,将下面这行C#代码翻译成VB时,每个变量需要一行:

var (key, value) = kvPair;

(By)Ref返回值

Ref返回值,也就是VB中的ByRef返回值,有严格的限制。你可以消费将一个引用(即托管指针)返回给一个字段或数组索引的C#函数,但你无法自己创建,你也无法创建局部ByRef变量。

你所能做的是采用一个相当复杂的变通方法。虽然你无法创建局部ByRef变量,但你可以创建ByRef参数。考虑下下面的C#函数和它在VB中的等价实现:

public ref string FindNext(string startWithString, ref bool found)ByRef Function FindNext(startWithString as string, ByRef found as Boolean) As String

要使用这个函数,Klaus Löffelmann告诉我们,我们需要一个辅助函数:

Private Function VbByRefHelper(Of t)(ByRef byRefValue As t,byRefSetter As Func(Of t, t)) As tDim orgValue = byRefValuebyRefValue = byRefSetter(byRefValue)Return orgValueEnd Function

接下来,你可以将返回ref的函数的结果作为参数传递给辅助函数,同时,你希望将其作为一个单独的匿名函数。

Dim didFind As Boolean'版本#2: 借助一个简单的泛型辅助类:aSentence = New NewInCS2017.Sentence("Adrian is going to marry Adriana, because Adrian loves Adriana.")DoVbByRefHelper(aSentence.FindNext("Adr", didFind),Function(stringFound) As StringIf stringFound = "Adrian" ThenstringFound = "Klaus"Return stringFoundEnd IfReturn stringFoundEnd Function)Loop While didfind

以下是VB完全实现Ref返回值后的样子,仅供参考:

'THIS DOES NOT WORK IN VB!!!Dim aSentence = New Sentence("Adrian is going to marry Adriana, because Adrian loves Adriana.")Dim found = FalseDo' !!In C# we can declare a local variable as ref - in VB we cannot.!!'   This variable could take the result...Dim ByRef foundString = aSentence.FindNext("Adr", found)If foundString = "Adrian" Then' but via the reference, so writing would be possible as well,' and we had a neat find and replace!foundString = "Klaus"End IfLoop While found

那么,VB为什么没有实现ref局部变量呢?

从根本上说是因为还没有东西使用它们。在.NET API中,目前没有任何东西需要使用它们,这个特性最终可能还是会走进死胡同。这以前发生过;几乎没有人使用不安全块,即使在使用原生C程序库时。栈分配数组的情况也一样。

Anthony Green写道:

坦白说,VB2017提供消费ref-returning函数的功能是为了对冲未来的不确定性,而不是为了让那个特性成为主流(即使在C#中也是如此)。

[…]

如果你看一下C#的这个版本,该特性带来了另一个特性,即ref局部变量。关于ref局部变量,也有一些考虑,ref再赋值(将一个局部变量“指向”另一个位置)以及ref局部变量默认只读,如何在所有可以引入变量的地方指定ref,区分普通赋值和ref赋值,类似这样的决策都需要在VB中解决,以便获得同样的生产能力。有大量的工作要做。

在VB中,工作量会更大,因为VB有额外的功能使用了ByRef,比如传递ByRef属性。VB编译器开发负责人Jared Parsons有一篇不错的博文,列举了许多在VB中使用ByRef的案例,可以说明这一点。返回一个ByRef属性,并在一个后期绑定的上下文中处理ByRef真得没有任何意义,因此, 与令人费解的ByRef参数相比,该语言对ByRef返回值的处理方式有所不同(而Jared现在得将更多的案例补充到那篇博文了)。那会给VB带来大量的困惑、语法和概念负担,因为C#增加了一项某一天可能用于编写一个集合类型的特性。

相反,我们采用一种不同的方法。简而言之,我们仅仅实现消费场景所需的特性,让你使用Slice(或者类似的返回ref的东西)就刚好可以完成你可以对数组进行的操作,除此之外,不提供任何额外的特性。当你使用索引指定一个数组元素时,你可以直接给它赋值,但你不能将数组元素的引用赋值给ref局部变量,并稍后再赋值给数组,你可以在那个索引指定的位置对值进行修改,你可以传递那个ByRef元素,但不能返回ByRef。也就是说,没有新语法,VB得到了保护。如果在VS2017发布之后,该语言的下一个版本发布之前,我们增加了Slice,而它作为一个集合类型,成了所有集合类型的终结者,一夜之间出现了数百万计的API返回ByRef类型。如果这个可能性微乎其微的噩梦永远不会发生,那么该语言就不会受此损害。这就是为什么它要那样设计。

(感兴趣的读者可以通过上面的链接阅读完整解释)

VB不是唯一一门这样做的语言。同样的考虑使得C#没有包含对XML库的支持,许多ASP.NET MVC开发人员都会希望它有这个特性。

原文地址:http://www.infoq.com/cn/news/2017/04/VB-15


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

Visual Basic 15语言新特性相关推荐

  1. JDK 15 JAVA 15的新特性展望

    文章目录 JEP 371: Hidden Classes JEP 372: 删除 Nashorn JavaScript Engine JEP 377: 新的垃圾回收器ZGC正式上线了 JEP 378: ...

  2. 老树新芽 体验Visual Basic 9.0新功能

    前言 "Visual Basic code-named Orcas"(Visual Basic 9.0)对基于"Visual Basic code-named Whidb ...

  3. SQL Server 2019 (15.x) 新特性概要

    2019.11.4 SQL Server 2019发布,趁热打铁了解下2019的新特性.下面整理一些个人感觉重要的或者工作上能用到的新特性,有删减,完整版参考 SQL Server 2019 中的新增 ...

  4. C++11语言新特性-《C++标准库(第二版)》读书笔记

    文章目录 3.1.1 微小但重要的语法提升 Template 表达式内的空格 nullptr 和std::nullptr_t 3.1.2 以auto 完成自动类型推导 3.1.3 一致性初始化(Uni ...

  5. Visual Studio 剪切板新特性

    以前开始学习编程时,一直使用Borland的开发工具,从TC2.0到BC3.1,再到BCB,delphi,每次更新工具或者版本时,无不为其人性化的新特性.新功能而陶醉不已.在BCB6,delphi6中 ...

  6. jQuery1.4的15个新特性实例精讲

    为什么80%的码农都做不了架构师?>>>    jQuery 1.4 的发布超乎大家的预期,这次并非简单的修修补补,1.4 包含了很多新特性.功能增强和性能提升!本文即向您介绍这些可 ...

  7. Visual C# 3.0 新特性概览

    在发布Visual Studio 2005和C#2.0之后,微软公司又马不停蹄的展示了人们所期望的C#的下一代版本:C# 3.0.尽管C# 3.0并没有标准化,微软还是在PDC(专业程序员会议)发布了 ...

  8. Visual C#3.0新特性概览

    在发布Visual Studio 2005和C#2.0之后,微软公司又马不停蹄的展示了人们所期望的C#的下一代版本:C# 3.0.尽管C# 3.0并没有标准化,微软还是在PDC(专业程序员会议)发布了 ...

  9. swift语言新特性:可选值

    var  a?  此处的a就是个可选值,意思是该值可能是缺失的. 可选 使用可选(optionals)来处理值可能缺失的情况.可选表示: -有值,等于 x 或者 没有值 注意:C 和 Objectiv ...

最新文章

  1. Paddle Lite端侧部署
  2. Realm数据库存储 使用详解
  3. 《深入理解Java虚拟机》笔记6——高效并发
  4. 卷积神经网络只是一种全连接神经网络的特殊情况
  5. linux查询tcp异常,linux服务器内存cpu 流量tcp异常信息记录python脚本
  6. H5 Canvas下雨特效
  7. 【bzoj1727】[Usaco2006 Open]The Milk Queue 挤奶队列 贪心
  8. 学习进度条__软件工程概论第一周学习计划
  9. 上海工程技术大学c语言试卷,上海工程技术大学2009-2010C语言试卷A.doc
  10. 《SQL高级应用和数据仓库基础(MySQL版)》学习笔记 ·003【表的约束、表的CRUD操作(DDL语句)】
  11. mysql主从同步开启后的iptables的设定问题
  12. iTunes恢复系统显示正在等待iPhone解决步骤
  13. 初中三年级数学可以用计算机吗,不到3分钟,这份初中数学攻略被家长和学生疯狂转发!太实用了!...
  14. 芯片SA58672(功放芯片)
  15. Eureka学习过程
  16. 危害人类健康的饮食“凶徒” 都是人造的
  17. ArcGIS中使用协同克里金插值(co-kriging interplotation )对气象数据插值
  18. 面向对象之唐城NBA选秀大会
  19. Java基础之IO流(持续更新中)
  20. cmos管宽长比,OC, OD门和线与逻辑,传输门,竞争冒险,三态门

热门文章

  1. [译]9条关于高性能ElasticSearch的配置建议
  2. swf 文件在线播放的,怎么能够下载呢?(除视频外其它都可)
  3. Java基础知识回顾--线程
  4. .NET WinForm程序中给DataGridView表头添加下拉列表实现数据过滤
  5. 加速你的Hibernate引擎(上)
  6. 组装电脑教程(转载)
  7. Exchange 2010发现拓扑失败
  8. 转:Chrome渲染分析之Timeline工具的使用
  9. JavaScript中使Promise模式进行异步编程
  10. 巧合?模仿还是抄袭?水木年华的《秋日恋歌》和Lube 乐队的《Pozovi Menya Tiho Po Imeni》...