Visual Basic 14 的 14 大新特性

与Visual Studio类似,Visual Basic也将从版本12直接跳到14。虽然新版本中的许多特性对于C#来说也是首次引进,但仍然有大量的功能增强是特别针对VB的,旨在简化VB的使用。本文列举了一些最令我们感兴趣的特性。

对Null的支持

新版本的一个特性是对null值的支持,该特性使用?.操作符。这一特性与C#相同,如果操作符左方的表达式返回值不为null,则继续计算右方表达式。在处理外部资源所返回的少量数据时,该特性尤其有用。举例来说:

If customer.PrimaryResidence IsNot Nothing AndAlso customer.PrimaryResidence.Garage IsNot Nothing AndAlso property.PrimaryResidence.Garage.Cars = 2 Then Print(“Two Car Garage”)

这段代码将被简化成以下语句:

If property.PrimaryResidence?.Garage?.Cars = 2 Then Print("Two Car Garage")

除此之外,还可以将该操作符与If操作符进行结合,实现为表达式提供某个默认值的功能:

Dim numberOfCarPorts = If(property.PrimaryResidence?.Garage?.Cars, 0)

C#与VB并不是唯一两种支持这种null处理方式的语言。在Apple的产品中得到广泛应用的Objective-C语言默认就支持该行为。尤其是它的方法调用也使用.操作符,其工作方式就类似于VB中的?.操作符。

在Objective-C的社区中,人们对该特性的评价褒贬不一。某些开发者非常喜爱这项功能,因为他们在进行方法调用时无需担心空引用异常的产生。而另一些开发者则对此感到痛恨,因为在问题发生时,他们不会看到空引用异常的产生,只会看到方法调用失败。如此一来他们就会感到困惑,为什么方法返回了null,而不是返回有效值或抛出异常。

元编程

在Visual Basic 12中,我们首次看到了CallerNameAttribute这一特性的引入。虽然这一特性解决了属性变更通知(property change notification)的问题,但它的通用性还不足以解决另外一部分问题,在这些问题中需要一个以字符串形式表达的唯一标识符,在这种情况下,需要使用到NameOf这个操作符。

以下这个示例是由来自Visual Basic团队的Lucian Wischik所提供的,其中包括对参数进行验证的逻辑。

Function Lookup(name As String) As Customer

If name is Nothing Then Throw New ArgumentNullException(NameOf(name))

这种方式能够避免在修改了参数名称的时候,忘记修改了所抛出异常的构造函数中所定义的字符串。由于NameOf操作符实际上创建了一个常量,因此你可以在任何需要使用硬编码字符串的时候使用该操作符。

字符串插值(Interpolation)

自从十年以前.NET初次问世的时候,String.Format这个方法就要求开发者们对参数的数量进行计数。多年以来,由于计数错误所产生的bug可谓是不计其数。字符串插值这一技术最初是由Mono团队为C#语言所创建的,它彻底解决了计数这种糟糕的做法。

插值字符串是由$”开头的,而不是单单使用”。对于每个你需要插入值的位置,都要使用一对大括号进行转义,这一点与String.Format的做法是相同的。另一个与String.Format相同的地方在于可以在转义中加入格式化选项。在下面这个简单的示例中出现了两个变量,name和total,后者将被格式化为货币格式。

Dim message = $"Hello {name}, your amount due is {total:C2}"

该语法本身就使用了String.Format方法,因此使用者同样需要注意在适当的场合进行转义,考虑一下以下字符串:

Dim requestUrl = $"http://{server}/customer?name={customerName}"

这段代码会产生一个bug,开发者实际上需要的是以下代码:

Dim requestUrl = $"http://{server}/customer?name={UrlEncode(customerName)}"

FormattedString对象

乍一看插值字符串的语法,似乎无法处理从外部资源中获取字符串的场景,例如从本地化表或资源字典中获取字符串。不过,微软正在努力实现这一功能。Lucian Wischik写道:

不仅能够使用在不同的语言文化中,而且还能够从中抽取出原始的格式化字符串或者是参数(举例来说,如果你打算在SQL查询中使用该语法,或者会需要对参数进行转义,以避免产生字符串注入攻击)。但目前为止,我们还没有完全决定该语法的设计规格。

按照当前的规格声明草稿所说,插值字符串可以是一个常规的字符串,也可以由一个名为FormattedString的对象实现。当你试图将某个插值字符串赋值给一个实现了IFormattable接口的变量或是参数时,系统会自动创建一个FormattedString类型的实例。

该对象的IFormattable.ToString方法接受一个类型为IFormatProvider类型的参数,使用该参数能够重写格式化相关的行为。

string IFormattable.ToString(string ignored, IFormatProvider formatProvider)
        {
            return String.Format(formatProvider, format, args);
        }

在上面一段代码中,format与args两个参数分别代表了待插值的原始字符串,以及它所对应的值。

多行字符串

在VB中新加入的一个特性是多行字符串。实现它不需要任何特殊的语法,只需要在希望分行的地方省略引号即可。根据源代码文件所使用的换行符的不同,该换行符会自动在vbCrlf、vbCr及vbLf等符号间进行选择。对于Visual Studio的用户来说,基本上都会选择vbCrlf。

在目前,某些开发者会选择在XML文本中使用CData段落来模仿这一特性,这种方式虽然能够实现所需要的效果,但显得有些冗长与笨拙。

属性

自动属性现在可以标记为只读了。可以在声明时为该属性赋值,也可在构造函数中进行赋值。

该语法的使用方式应该不会出乎你的意料:

Public ReadOnly FirstName As String = "Anonymous"
Public ReadOnly LastName As String
Public Sub New (firstName As String, lastName As String)
    Me.FirstName = firstName
    Me.LastName = lastName
End Sub

在使用这一特性时,应当考虑到某些特殊情况。要理解这些情况,你首先必须理解参数传递的copy-in和copy-out概念。CLR只允许你为变量及字段进行引用传递(即C#中的ref或out操作符)。但在VB中,你也能够为属性进行引用传递。

为了缓解这两者之间的分歧,VB会在准备进行函数调用时创建一个本地变量,该属性的值会被拷贝到这个本地变量中。该本地变量随后被传递至函数中,函数体能够修改该本地变量的值。当该函数返回时,本地变量的值会拷贝回属性中。

在使用只读的自动属性时,将会应用以下规则:

  1. 如果你在构造函数中的某个lambda表达式中使用只读自动属性,编译器会提示语法错误。
  2. 如果在构造函数或初始化器中使用只读自动属性,将应用copy-in与copy-out规则。Copy-out操作会将值写入系统为属性生成的字段中。
  3. 如果不在构造函数或初始化器中使用只读自动属性,则只会应用copy-in规则。Copy-out操作根本不会发生,但也不会产生任何语法错误。

这些规则都是基于只读字段的工作原理所产生的。

注释

现在,在一个多行语句的每一行末尾都可以加入注释了。在之前的版本中,只能在多行语句的最后一行末尾加入注释。请看以下示例:

Dim emailList =
    From c in Customers
    Where c.IsActive ‘ignore inactive customers
    And Not c.DoNotEmail ‘we don’t need another spam violation
    Select c.FullName, c.EmailAddress

结构体

结构体现在能够支持无参构造函数了。虽然CLR本身就支持这一特性,但还没有主流的编程语言实现了这一特性,其原因是构造函数的运行时机并不明确。举例来说,在创建某个结构体的数组时,该结构体的构造函数并不会运行。

如果你的代码是myStruct = new MyStructure(),那很显然该构造函数会立即执行。而如果你的代码是myStruct = Nothing,则显然不会执行构造函数。但在某个本地变量或成员变量自动初始化时又是否会执行构造函数呢?无论你选择哪一种答案,总会让一部分人感觉不爽。

数据文本(Data Literals)

从今年开始,数据文本(对于JSON格式来说非常重要的一个特性)终于改为使用符合ISO标准的格式了。在过去,数据文本一直使用基于美国的格式化形式,对于居住在欧洲的人来说就会产生一些迷惑。

  • 老风格:#3/4/2005#(是三月四日,还是四月三日?)
  • 新风格:#2005-4-3#

与C#的互操作性

Overrides修饰符将会隐含使用Overloads修饰符。在过去,VB的开发者必须同时使用这两种修饰符,才能保证C#的使用者在使用由VB所创建的类库时能够调用正确的重载方法。

接口模糊性

在C#中使用接口继承这一特性时,会造成不易判断到底是哪个接口方法被调用的问题。在VB中不允许出现这种场景,但由于C#允许这一特性,会造成出现某些VB无法实现的接口的情况。(在Microsoft Dynamics的某个产品中就数次出现这种情况。)

相对于C#中所使用的“通过名称隐藏”(hide-by-name)的重载规则,VB 14中将对这一限制进行放宽,转而使用一种(对VB来说)更传统的方式,即“通过签名隐藏”的规则。

命名空间解析

VB也曾在命名空间解析这一问题上栽过跟斗,考虑一下以下代码:

Threading.Thread.Sleep(1000)

按Lucian Wischik所说:

之前,VB会尝试查找“Threading”这一命名空间,由于它无法分辨System.Threading和System.Windows.Threading的区别,因此直接报错。现在,VB14会同时支持这两种可能匹配的命名空间。如果你在代码编辑器输入Threading.,那么在输入.号之后,你会在智能提示中看到对这两个命名空间的支持。

类似的情况还有许多,举例来说:在编写Winforms应用时,ComponentModel.INotifyPropertyChanged事件就会无法分辨System.ComponentModel及System.Windows.Forms.ComponentModel,这一问题如今将不复存在。

TypeOf和IsNot

微软在十年前就创建了IsNot操作符,自那以来,就不断有VB的开发者要求微软允许在TypeOf表达式中使用IsNot操作符,举例如下:

If TypeOf sender IsNot Button Then

预处理指令

VB 14为预处理指令提供了两点改进之处。

Regi7on

Region将能够在函数体中进行使用,甚至是跨两个函数体进行使用。

关闭警告

与C#相同,Visual Basic现在也能够关闭对某一个代码块的编译警告了。在规格说明中提供了一个示例:

#Disable Warning BC42356 ‘suppress warning about no awaits in this method

通常来说,开发者会通过某个指令在该代码文件的其它地方重新打开这一警告

#Enable Warning BC42356

如果该警告的ID中包含了空格或标点符号,则必须使用引号。微软的工具不会自动为你完成这一点,不过由Roslyn所编写的第三方分析器规则或许能实现这一点。

VB的快速修复(Quick Fix)特性能够通过自动添加这些指令实现绕过某些警告的目的。这一点对于之前提到的第三方分析器规则来说尤其有用,因为你不一定能够很快地找到对应的ID。

XML文档验证

目前来说,VB编译器会忽略XML文档的内容。而在VB 14中,编译器就会试图在文档中查找错误,例如不正确的参数引用名称。它还能够“正确地处理crefs标签中的泛型与操作符”。

部分模块(partial module)与接口声明

与类和结构体类型,你现在能够将模块与接口声明为部分(partial)了。通常来说,这一特性是为代码生成器所准备的,但也能够在跨多个平台分享代码时发挥作用。

时间: 2024-08-28 19:31:49

Visual Basic 14 的 14 大新特性的相关文章

有史来最大改变 Android 5.0十大新特性

有史来最大改变 Android 5.0十大新特性 2014.10.16 14:51:31 来源:腾讯数码作者:腾讯数码 ( 0 条评论 ) 距离Android系统上一次重大更新不到一年的时间,谷歌再一次从KitKat升级到了Lollipop,而两次都使用糖果来命名,营销的目的显露无 遗.当我们首次看到Android 5.0 Lollipop这个名字的时候,就已经意识到这将是Android系统有史以来变化最大的一次升级. 首先,在感官界面设计上,我们彻底迎来了Android系统的扁平化时代,新的系

java8的十大新特性

推荐学习的博客:http://blog.csdn.net/renfufei/article/details/24600507/-------讲解的非常通俗易懂 Java 9预计将于今年9月份发布,这是否会是一次里程碑式的版本,我们拭目以待.今天,我们先来复习一下2014年发布的Java 8的十大新特性. Java 8可谓是自Java 5以来最具革命性的版本了,她在语言.编译器.类库.开发工具以及Java虚拟机等方面都带来了不少新特性.我们来一一回顾一下这些特性. 一.Lambda表达式 Lamb

Java9都快发布了,Java8的十大新特性你了解多少呢?

Java 9预计将于今年9月份发布,这是否会是一次里程碑式的版本,我们拭目以待.今天,我们先来复习一下2014年发布的Java 8的十大新特性. Java 8可谓是自Java 5以来最具革命性的版本了,她在语言.编译器.类库.开发工具以及Java虚拟机等方面都带来了不少新特性.我们来一一回顾一下这些特性. 一.Lambda表达式 Lambda表达式可以说是Java 8最大的卖点,她将函数式编程引入了Java.Lambda允许把函数作为一个方法的参数,或者把代码看成数据. 一个Lambda表达式可

java6新特性(简述十大新特性)

十大新特性(其实都比较鸡肋,对开发者来说)1.Web Services优先支持编写 XML web service 客户端程序.你可以用过简单的annotaion将你的API发布成.NET交互的web services. Mustang 添加了新的解析和 XML 在 Java object-mapping APIs中, 之前只在Java EE平台实现或者Java Web Services Pack中提供. 2.Scripting(开启JS的支持,算是比较有用的)现在你可以在Java源代码中混入J

JDK8-十大新特性-附demo

JDK原计划17年上半年就发版,但未成功发版.才发现JDK8的特性还没总结过,特此总结. 一.十大特性. 1.Lambda表达式 2.Stream函数式操作流元素集合 3.接口新增:默认方法与静态方法 4.方法引用,与Lambda表达式联合使用 5.引入重复注解 6.类型注解 7.最新的Date/Time API (JSR 310) 8.新增base64加解密API 9.数组并行(parallel)操作 10.JVM的PermGen空间被移除:取代它的是Metaspace(JEP 122)元空间

JAVA8 十大新特性详解

本教程将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API上的改进,比如流,函数式接口,Map以及全新的日期API “Java is still not dead—and people are starting to figure that out.” 本教程将用带注释的简单代码来描述新特性,你将看不到大片吓人的文字. 一.接口的默认方法 Java 8允许我们给接口添加一个非抽象的方

java8十大新特性浅谈

本文将Java8的新特新逐一列出,并将使用简单的代码示例来指导你如何使用默认接口方法,lambda表达式,方法引用以及多重Annotation,之后你将会学到最新的API上的改进,比如流,函数式接口,Map以及全新的日期API "Java is still not dead-and people are starting to figure that out." 本文将用带注释的简单代码来描述新特性,你将看不到大片吓人的文字. 一.接口的默认方法 Java 8允许我们给接口添加一个非抽

[Android 新特性] 有史来最大改变 Android 5.0十大新特性

距离Android系统上一次重大更新不到一年的时间,谷歌再一次从KitKat升级到了Lollipop,而两次都使用糖果来命名,营销的目的显露无 遗.当我们首次看到Android 5.0 Lollipop这个名字的时候,就已经意识到这将是Android系统有史以来变化最大的一次升级. 首先,在感官界面设计上,我们彻底迎来了Android系统的扁平化时代,新的系统不仅使用了新的配色,同时看起来也很时尚.未来我们相信包括三星的TouchWiz或LG的Optimus自定义UI都会遵循Lollipop的新

Java 9 逆天的十大新特性

在介绍 Java 9 之前,我们先来看看 Java 成立到现在的所有版本. 1990 年初,最初被命名为 Oak:1995 年 5 月 23 日,Java 语言诞生:1996 年 1 月,第一个 JDK-JDK 1.0 诞生:1996 年 4 月,10 个最主要的操作系统供应商申明将在其产品中嵌入 Java 技术:1996 年 9 月,约 8.3 万个网页应用了 Java 技术来制作:1997 年 2 月 18 日,JDK 1.1 发布:1997 年 4 月 2 日,JavaOne 会议召开,参