Visual Basic 15语言新特性
對于C#的兩個重要特性元組和Ref返回值,Visual Basic 15提供了對等的實現(xiàn)。這兩個特性都是“不完全的”,但已經(jīng)可以提供足夠的變通方案,讓VB應用程序可以消費使用了這些特性的C#庫。
元組
在VB中,從單個函數(shù)調(diào)用直接返回多個值是一個人們期待已久的特性。雖然開發(fā)人員可以使用ByRef參數(shù)獲得同樣的結(jié)果,但與函數(shù)式編程語言相比,其語法相當笨拙。
你可能不熟悉這個術(shù)語,“元組”就是一組相關(guān)的值。從.NET 4.0開始,Visual Basic就提供了一個標準的Tuple類,但用戶體驗不那么令人滿意。開發(fā)人員必須手動解包來獲得Tuple的值,而且要使用Item1、Item2等不能提供什么幫助的屬性名。
七年之后,VB 15終于為元組提供了語法支持。更確切地說,與堆分配Tuple對象相比,ValueTuple結(jié)構(gòu)提供了更好的性能。下面是一個例子,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。這使得函數(shù)更簡潔了一些,因為你不必再顯式說明ValueTuple類型。但是,如你所見,調(diào)用它的代碼沒有任何不同。因此,讓我們稍微改進一下,但保持返回類型的字段不變:
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你可以使用下面的語法創(chuàng)建帶有命名字段的元組:
Dim kvPair = (Key := 5, Value := "Five")遺憾的是,VB沒有提供一種可以將元組“解包”到多個變量的方法。因此,將下面這行C#代碼翻譯成VB時,每個變量需要一行:
var (key, value) = kvPair;(By)Ref返回值
Ref返回值,也就是VB中的ByRef返回值,有嚴格的限制。你可以消費將一個引用(即托管指針)返回給一個字段或數(shù)組索引的C#函數(shù),但你無法自己創(chuàng)建,你也無法創(chuàng)建局部ByRef變量。
你所能做的是采用一個相當復雜的變通方法。雖然你無法創(chuàng)建局部ByRef變量,但你可以創(chuàng)建ByRef參數(shù)。考慮下下面的C#函數(shù)和它在VB中的等價實現(xiàn):
public ref string FindNext(string startWithString, ref bool found)ByRef Function FindNext(startWithString as string, ByRef found as Boolean) As String要使用這個函數(shù),Klaus L?ffelmann告訴我們,我們需要一個輔助函數(shù):
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的函數(shù)的結(jié)果作為參數(shù)傳遞給輔助函數(shù),同時,你希望將其作為一個單獨的匿名函數(shù)。
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完全實現(xiàn)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為什么沒有實現(xiàn)ref局部變量呢?
從根本上說是因為還沒有東西使用它們。在.NET API中,目前沒有任何東西需要使用它們,這個特性最終可能還是會走進死胡同。這以前發(fā)生過;幾乎沒有人使用不安全塊,即使在使用原生C程序庫時。棧分配數(shù)組的情況也一樣。
Anthony Green寫道:
坦白說,VB2017提供消費ref-returning函數(shù)的功能是為了對沖未來的不確定性,而不是為了讓那個特性成為主流(即使在C#中也是如此)。
[…]
如果你看一下C#的這個版本,該特性帶來了另一個特性,即ref局部變量。關(guān)于ref局部變量,也有一些考慮,ref再賦值(將一個局部變量“指向”另一個位置)以及ref局部變量默認只讀,如何在所有可以引入變量的地方指定ref,區(qū)分普通賦值和ref賦值,類似這樣的決策都需要在VB中解決,以便獲得同樣的生產(chǎn)能力。有大量的工作要做。
在VB中,工作量會更大,因為VB有額外的功能使用了ByRef,比如傳遞ByRef屬性。VB編譯器開發(fā)負責人Jared Parsons有一篇不錯的博文,列舉了許多在VB中使用ByRef的案例,可以說明這一點。返回一個ByRef屬性,并在一個后期綁定的上下文中處理ByRef真得沒有任何意義,因此, 與令人費解的ByRef參數(shù)相比,該語言對ByRef返回值的處理方式有所不同(而Jared現(xiàn)在得將更多的案例補充到那篇博文了)。那會給VB帶來大量的困惑、語法和概念負擔,因為C#增加了一項某一天可能用于編寫一個集合類型的特性。
相反,我們采用一種不同的方法。簡而言之,我們僅僅實現(xiàn)消費場景所需的特性,讓你使用Slice(或者類似的返回ref的東西)就剛好可以完成你可以對數(shù)組進行的操作,除此之外,不提供任何額外的特性。當你使用索引指定一個數(shù)組元素時,你可以直接給它賦值,但你不能將數(shù)組元素的引用賦值給ref局部變量,并稍后再賦值給數(shù)組,你可以在那個索引指定的位置對值進行修改,你可以傳遞那個ByRef元素,但不能返回ByRef。也就是說,沒有新語法,VB得到了保護。如果在VS2017發(fā)布之后,該語言的下一個版本發(fā)布之前,我們增加了Slice,而它作為一個集合類型,成了所有集合類型的終結(jié)者,一夜之間出現(xiàn)了數(shù)百萬計的API返回ByRef類型。如果這個可能性微乎其微的噩夢永遠不會發(fā)生,那么該語言就不會受此損害。這就是為什么它要那樣設計。
(感興趣的讀者可以通過上面的鏈接閱讀完整解釋)
VB不是唯一一門這樣做的語言。同樣的考慮使得C#沒有包含對XML庫的支持,許多ASP.NET MVC開發(fā)人員都會希望它有這個特性。
原文地址:http://www.infoq.com/cn/news/2017/04/VB-15
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的Visual Basic 15语言新特性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: asp.net core源码飘香:Log
- 下一篇: 初探CSRF在ASP.NET Core中