Visual Basic 15语言新特性

对于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) Try Dim numericValue = Integer.Parse(s) Return (True, numericValue) Catch Return (False, Nothing) End Try End Function Dim result = TryParse(s) If result.Item1 Then WriteLine(result.Item2) End If

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

Public Function TryParse(s As String) As (IsInteger As Boolean, Value As Integer) … End Function Dim result = TryParse(s) If result.IsInteger Then WriteLine(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 t Dim orgValue = byRefValue byRefValue = byRefSetter(byRefValue) Return orgValue End Function

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

Dim didFind As Boolean '版本#2: 借助一个简单的泛型辅助类: aSentence = New NewInCS2017.Sentence("Adrian is going to marry Adriana, because Adrian loves Adriana.") Do VbByRefHelper(aSentence.FindNext("Adr", didFind), Function(stringFound) As String If stringFound = "Adrian" Then stringFound = "Klaus" Return stringFound End If Return stringFound End 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 = False Do ' !!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 If Loop While found

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

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

Anthony Green写道

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

[…]

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/055e90886a2518182a409b9e1beede25.html