Visual Basic 的新功能What's new for Visual Basic

此主題列出每個 Visual Basic 版本的主要功能名稱,並詳細說明該語言最新版本的新功能與增強功能。This topic lists key feature names for each version of Visual Basic, with detailed descriptions of the new and enhanced features in the latest versions of the language.

目前版本Current version

Visual Basic 16.0/Visual Studio 2019 版本 16.0 Visual Basic 16.0 / Visual Studio 2019 version 16.0
如需新功能,請參閱Visual Basic 16.0For new features, see Visual Basic 16.0.

舊版本Previous versions

Visual Basic 15.8/Visual Studio 2017 版本 15.8 Visual Basic 15.8 / Visual Studio 2017 version 15.8
如需新功能,請參閱Visual Basic 15.8For new features, see Visual Basic 15.8.

Visual Basic 15.5/Visual Studio 2017 版本 15.5 Visual Basic 15.5 / Visual Studio 2017 version 15.5
如需新功能,請參閱Visual Basic 15.5For new features, see Visual Basic 15.5.

Visual Basic 15.3/Visual Studio 2017 版本 15.3 Visual Basic 15.3 / Visual Studio 2017 version 15.3
如需新功能,請參閱Visual Basic 15.3For new features, see Visual Basic 15.3.

Visual Basic 2017/Visual Studio 2017 Visual Basic 2017 / Visual Studio 2017
如需新功能,請參閱Visual Basic 2017For new features, see Visual Basic 2017.

Visual Basic/Visual Studio 2015 Visual Basic / Visual Studio 2015
如需新功能,請參閱Visual Basic 14For new features, see Visual Basic 14.

Visual Basic/Visual Studio 2013 Visual Basic / Visual Studio 2013
.NET 編譯器平台 ("Roslyn") 的技術預覽Technology previews of the .NET Compiler Platform (“Roslyn”)

Visual Basic/Visual Studio 2012 Visual Basic / Visual Studio 2012
Asyncawait 關鍵字、迭代器、呼叫端資訊屬性Async and await keywords, iterators, caller info attributes

Visual Basic,Visual Studio 2010 Visual Basic, Visual Studio 2010
自動實作的屬性、集合初始設定式、隱含行接續符號、動態、泛型共變數/反變數、全域命名空間存取Auto-implemented properties, collection initializers, implicit line continuation, dynamic, generic co/contra variance, global namespace access

Visual Basic/Visual Studio 2008 Visual Basic / Visual Studio 2008
Language Integrated Query (LINQ)、XML 常值、區域類型推斷、物件初始設定式、匿名類型、擴充方法、區域 var 類型推斷、Lambda 運算式、if 運算子、部分方法、可為 Null 的實值類型Language Integrated Query (LINQ), XML literals, local type inference, object initializers, anonymous types, extension methods, local var type inference, lambda expressions, if operator, partial methods, nullable value types

Visual Basic/Visual Studio 2005 Visual Basic / Visual Studio 2005
My 類型和協助程式類型 (應用程式、電腦、檔案系統、網路的存取)The My type and helper types (access to app, computer, files system, network)

Visual Basic/Visual Studio .NET 2003 Visual Basic / Visual Studio .NET 2003
位元移位運算子、迴圈變數宣告Bit-shift operators, loop variable declaration

Visual Basic/Visual Studio .NET 2002 Visual Basic / Visual Studio .NET 2002
第一版的 Visual Basic .NETThe first release of Visual Basic .NET

Visual Basic 16.0Visual Basic 16.0

Visual Basic 16.0 著重于為 .NET Core 提供 Visual Basic 執行時間(microsoft)的更多功能,而且是著重于 .NET Core Visual Basic 的第一個版本。Visual Basic 16.0 focuses on supplying more of the features of the Visual Basic Runtime (microsoft.visualbasic.dll) to .NET Core and is the first version of Visual Basic focused on .NET Core. Visual Basic 執行時間的許多部分都取決於 WinForms,而這些會在較新版本的 Visual Basic 中新增。Many portions of the Visual Basic Runtime depend on WinForms and these will be added in a later version of Visual Basic.

語句中的多個位置允許的批註Comments allowed in more places within statements

在 Visual Basic 15.8 和更早版本中,只允許在空白行、語句結尾,或在允許隱含行接續的語句中的特定位置使用批註。In Visual Basic 15.8 and earlier versions, comments are only allowed on blank lines, at the end of a statement, or in specific places within a statement where an implicit line continuation is allowed. 從 Visual Basic 16.0 開始,在明確的行接續之後,以及在行首加上底線的空格後面的語句內,也允許批註。Starting with Visual Basic 16.0, comments are also allowed after explicit line continuations and within a statement on a line beginning with a space followed by an underscore.

Public Sub Main()
    cmd.CommandText = ' Comment is allowed here without _
        "SELECT * FROM Titles JOIN Publishers " _ ' This is a comment
        & "ON Publishers.PubId = Titles.PubID " _
 _ ' This is a comment on a line without code
        & "WHERE Publishers.State = 'CA'"
End Sub

Visual Basic 15.8Visual Basic 15.8

最佳化的浮點數至整數轉換Optimized floating-point to integer conversion

在舊版的 Visual Basic 中,將 DoubleSingle 值轉換成整數會提供相對較差的效能。In previous versions of Visual Basic, conversion of Double and Single values to integers offered relatively poor performance. 當您將下列任一方法所傳回的值傳遞至其中一個內建的 Visual Basic 整數轉換函式(CByte、CShort、CInt、CLng、CSByte、CUShort、CUInt、CULng) 時,或在 Option Strict 設定為 Off 的情況下,將下列任一方法所傳回的值隱含地轉換成整數類型時,Visual Basic 15.8 可大幅增強浮點數轉換成整數的效能:Visual Basic 15.8 significantly enhances the performance of floating-point conversions to integers when you pass the value returned by any of the following methods to one of the intrinsic Visual Basic integer conversion functions (CByte, CShort, CInt, CLng, CSByte, CUShort, CUInt, CULng), or when the value returned by any of the following methods is implicitly cast to an integral type when Option Strict is set to Off:

這項最佳化可讓程式碼執行速度更快,對於執行大量轉換 (目標為整數類型) 的程式碼,速度最快提高為兩倍。This optimization allows code to run faster -- up to twice as fast for code that does a large number of conversions to integer types. 下列範例說明一些受這項最佳化影響的簡單方法呼叫:The following example illustrates some simple method calls that are affected by this optimization:

Dim s As Single = 173.7619
Dim d As Double = s

Dim i1 As Integer = CInt(Fix(s))               ' Result: 173
Dim b1 As Byte = CByte(Int(d))                 ' Result: 173
Dim s1 AS Short = CShort(Math.Truncate(s))     ' Result: 173
Dim i2 As Integer = CInt(Math.Ceiling(d))      ' Result: 174
Dim i3 As Integer = CInt(Math.Round(s))        ' Result: 174

請注意,這會截斷而不是四捨五入浮點值。Note that this truncates rather than rounds floating-point values.

Visual Basic 15.5Visual Basic 15.5

非後置具名引數Non-trailing named arguments

在 Visual Basic 15.3 和更早版本中,當方法呼叫同時包含位置和名稱引數時,位置引數必須在具名引數之前。In Visual Basic 15.3 and earlier versions, when a method call included arguments both by position and by name, positional arguments had to precede named arguments. 從 Visual Basic 15.5 開始,位置和具名引數可依任何順序顯示,但前提是最後一個位置引數之前的所有引數都位於正確位置。Starting with Visual Basic 15.5, positional and named arguments can appear in any order as long as all arguments up to the last positional argument are in the correct position. 當使用具名引數讓程式碼更容易閱讀時,這會特別有用。This is particularly useful when named arguments are used to make code more readable.

例如,下列方法呼叫在具名引數之間有兩個位置引數。For example, the following method call has two positional arguments between a named argument. 具名引數清楚指出值 19 表示年齡。The named argument makes it clear that the value 19 represents an age.

StudentInfo.Display("Mary", age:=19, #9/21/1998#)

Private Protected 成員存取修飾詞Private Protected member access modifier

這個新的關鍵字組合能定義可由其包含類別中的所有成員,以及由衍生自該包含類別的類型 (但僅限於也能在包含組件中找到它們的情況下) 進行存取的成員。This new keyword combination defines a member that is accessible by all members in its containing class as well as by types derived from the containing class, but only if they are also found in the containing assembly. 由於結構無法被繼承,因此 Private Protected 只能套用至類別的成員。Because structures cannot be inherited, Private Protected can only be applied to the members of a class.

前置十六進位/二進位/八進位分隔符號Leading hex/binary/octal separator

Visual Basic 2017 新增了將底線字元 (_) 當作數字分隔符號的支援。Visual Basic 2017 added support for the underscore character (_) as a digit separator. 從 Visual Basic 15.5 開始,您可以使用底線字元作為前置字元與十六進位、二進位或八進位數字之間的前置分隔符號。Starting with Visual Basic 15.5, you can use the underscore character as a leading separator between the prefix and hexadecimal, binary, or octal digits. 下列範例使用前置數字分隔符號,將 3,271,948,384 定義為十六進位數字:The following example uses a leading digit separator to define 3,271,948,384 as a hexadecimal number:

Dim number As Integer = &H_C305_F860

若要使用底線字元作為前置分隔符號,您必須將下列項目新增至 Visual Basic 專案 (*.vbproj) 檔:To use the underscore character as a leading separator, you must add the following element to your Visual Basic project (*.vbproj) file:

<PropertyGroup>
  <LangVersion>15.5</LangVersion>
</PropertyGroup>

Visual Basic 15.3Visual Basic 15.3

具名元組推斷Named tuple inference

當您從變數指派元組項目值時,Visual Basic 會從對應的變數名稱推斷元組項目的名稱;您不需要明確命名元組項目。When you assign the value of tuple elements from variables, Visual Basic infers the name of tuple elements from the corresponding variable names; you do not have to explicitly name a tuple element. 下列範例使用推斷來建立包含三個具名項目的元組:statestateNamecapitalThe following example uses inference to create a tuple with three named elements, state, stateName, and capital.

Const state As String = "MI"
Const stateName As String = "Michigan"
Const capital As String = "Lansing"
Dim stateInfo = ( state, stateName, capital )
Console.WriteLine($"{stateInfo.stateName}: 2-letter code: {stateInfo.State}, Capital {stateInfo.capital}")   
' The example displays the following output:
'      Michigan: 2-letter code: MI, Capital Lansing

其他編譯器參數Additional compiler switches

Visual Basic 命令列編譯器現在支援 -refout -refonly 編譯器選項,來控制參考組件的輸出。The Visual Basic command-line compiler now supports the -refout and -refonly compiler options to control the output of reference assemblies. -refout 定義參考組件的輸出目錄,而 -refonly 指定編譯只會輸出參考組件。-refout defines the output directory of the reference assembly, and -refonly specifies that only a reference assembly is to be output by compilation.

Visual Basic 2017Visual Basic 2017

TupleTuples

Tuple 是輕量的資料結構,最常用於從單一方法呼叫傳回多個值。Tuples are a lightweight data structure that most commonly is used to return multiple values from a single method call. 通常要從方法傳回多個值,您必須執行下列其中一項︰Ordinarily, to return multiple values from a method, you have to do one of the following:

  • 定義自訂類型 (ClassStructure)。Define a custom type (a Class or a Structure). 這是重量級解決方案。This is a heavyweight solution.

  • 除了從方法傳回值外,定義一或多個 ByRef 參數。Define one or more ByRef parameters, in addition to returning a value from the method.

Tuple 的 Visual Basic 支援可讓您快速定義 Tuple、選擇性地將語意名稱指派給它的值,並快速地擷取其值。Visual Basic's support for tuples lets you quickly define a tuple, optionally assign semantic names to its values, and quickly retrieve its values. 下列範例會包裝對 TryParse 方法的呼叫,並傳回 Tuple。The following example wraps a call to the TryParse method and returns a tuple.

Imports System.Globalization

Public Module NumericLibrary
    Public Function ParseInteger(value As String) As (Success As Boolean, Number As Int32)
        Dim number As Integer
        Return (Int32.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, number), number)
    End Function
End Module

然後呼叫方法並使用類似下面的程式碼處理傳回的 Tuple。You can then call the method and handle the returned tuple with code like the following.

Dim numericString As String = "123,456"
Dim result = ParseInteger(numericString)
Console.WriteLine($"{If(result.Success, $"Success: {result.Number:N0}", "Failure")}")
Console.ReadLine()
'      Output: Success: 123,456

二進位常值和數字分隔符號Binary literals and digit separators

您可以使用前置詞 &B&b 來定義二進位常值。You can define a binary literal by using the prefix &B or &b. 此外,還可以使用底線字元 _ 當作數字分隔符號,提升可讀性。In addition, you can use the underscore character, _, as a digit separator to enhance readability. 下列範例會使用這兩種功能指派 Byte 值,並將它顯示為十進位、十六進位和二進位數字。The following example uses both features to assign a Byte value and to display it as a decimal, hexadecimal, and binary number.

Dim value As Byte = &B0110_1110
Console.WriteLine($"{NameOf(value)}  = {value} (hex: 0x{value:X2}) " +
                  $"(binary: {Convert.ToString(value, 2)})")
' The example displays the following output:
'      value  = 110 (hex: 0x6E) (binary: 1101110)      

如需詳細資訊,請參閱 ByteIntegerLongShortSByteUIntegerULongUShort 資料類型的<常值指派>一節。For more information, see the "Literal assignments" section of the Byte, Integer, Long, Short, SByte, UInteger, ULong, and UShort data types.

C# 參考傳回值的支援Support for C# reference return values

從 C# 7.0 開始,C# 支援參考傳回值。Starting with C# 7.0, C# supports reference return values. 也就是說,當呼叫方法收到參考傳回的值時,它可以變更參考的值。That is, when the calling method receives a value returned by reference, it can change the value of the reference. Visual Basic 不允許您撰寫使用參考傳回值的方法,但允許您使用和修改參考傳回值。Visual Basic does not allow you to author methods with reference return values, but it does allow you to consume and modify the reference return values.

例如,以 C# 撰寫的下列 Sentence 類別包含 FindNext 方法,它可以在句子中尋找以指定子字串開頭的下一個文字。For example, the following Sentence class written in C# includes a FindNext method that finds the next word in a sentence that begins with a specified substring. 字串會以參考傳回值傳回,而參考所傳遞至方法的 Boolean 變數會指出搜尋是否成功。The string is returned as a reference return value, and a Boolean variable passed by reference to the method indicates whether the search was successful. 這表示,呼叫端不只可以讀取傳回值,還可以修改它,再將修改結果反映在 Sentence 類別中。This means that the caller can not only read the returned value; he or she can also modify it, and that modification is reflected in the Sentence class.

using System;
 
public class Sentence
{
    private string[] words;
    private int currentSearchPointer;
    
    public Sentence(string sentence)
    {
        words = sentence.Split(' ');
        currentSearchPointer = -1;
    }
    
    public ref string FindNext(string startWithString, ref bool found)
    {
        for (int count = currentSearchPointer + 1; count < words.Length; count++)
        {
            if (words[count].StartsWith(startWithString))
            {
                currentSearchPointer = count;
                found = true;
                return ref words[currentSearchPointer];
            }
        }
        currentSearchPointer = -1;
        found = false;
        return ref words[0];
    }
    
    public string GetSentence()
    {
        string stringToReturn = null;
        foreach (var word in words)
            stringToReturn += $"{word} ";
      
        return stringToReturn.Trim();    
    }
}

在最簡單的格式中,您可以使用類似下列的程式碼,修改句子中找到的字。In its simplest form, you can modify the word found in the sentence by using code like the following. 請注意,您不是將值指派給方法,而是指派給方法傳回的運算式,也就是參考傳回值。Note that you are not assigning a value to the method, but rather to the expression that the method returns, which is the reference return value.

Dim sentence As New Sentence("A time to see the world is now.")
Dim found = False
sentence.FindNext("A", found) = "A good" 
Console.WriteLine(sentence.GetSentence()) 
' The example displays the following output:
'      A good time to see the world is now.

但此程式碼有個問題,亦即如果找不到相符的項目,方法會傳回第一個字。A problem with this code, though, is that if a match is not found, the method returns the first word. 因為範例不會檢查 Boolean 引數的值來判斷是否找到相符項目,所以如果找不到相符的項目,就會修改第一個字。Since the example does not examine the value of the Boolean argument to determine whether a match is found, it modifies the first word if there is no match. 如果找不到相符的項目,下列範例會用本身來取代第一個字,藉此更正這個問題。The following example corrects this by replacing the first word with itself if there is no match.

Dim sentence As New Sentence("A time to see the world is now.")
Dim found = False
sentence.FindNext("A", found) = IIf(found, "A good", sentence.FindNext("B", found)) 
Console.WriteLine(sentence.GetSentence()) 
' The example displays the following output:
'      A good time to see the world is now.

更好的解決方案是使用參考所傳遞之參考傳回值對象的協助程式方法。A better solution is to use a helper method to which the reference return value is passed by reference. 協助程式方法可以修改參考所傳遞給它的引數。The helper method can then modify the argument passed to it by reference. 下列範例正是如此。The following example does that.

Module Example
   Public Sub Main()
      Dim sentence As New Sentence("A time to see the world is now.")
      Dim found = False
      Dim returns = RefHelper(sentence.FindNext("A", found), "A good", found) 
      Console.WriteLine(sentence.GetSentence()) 
   End Sub
   
   Private Function RefHelper(ByRef stringFound As String, replacement As String, success As Boolean) _ 
                    As (originalString As String, found As Boolean) 
      Dim originalString = stringFound
      If found Then stringFound = replacement
      Return (originalString, found)   
   End Function
End Module
' The example displays the following output:
'      A good time to see the world is now.

如需詳細資訊,請參閱參考傳回值For more information, see Reference Return Values.

Visual Basic 14Visual Basic 14

NameOfNameOf

您可以取得用於錯誤訊息之類型或成員的未限定字串名稱,而不需要對字串進行硬式編碼。You can get the unqualified string name of a type or member for use in an error message without hard coding a string. 這可讓您的程式碼在重構時保持正確。This allows your code to remain correct when refactoring. 這項功能也可用來連接模型檢視控制器 MVC 連結,以及引發屬性已變更事件。This feature is also useful for hooking up model-view-controller MVC links and firing property changed events.

字串內插補點String interpolation

您可以使用字串插值運算式來建構字串。You can use string interpolation expressions to construct strings. 字串插值運算式類似包含運算式的範本字串。An interpolated string expression looks like a template string that contains expressions. 對於引數而言,字串插值比複合格式更容易了解。An interpolated string is easier to understand with respect to arguments than Composite Formatting.

Null 條件式成員存取和索引Null-conditional member access and indexing

您可以在執行成員存取 (?.) 或對 (?[]) 作業編製索引之前,透過非常精簡的語法來測試是否為 Null。You can test for null in a very light syntactic way before performing a member access (?.) or index (?[]) operation. 這些運算子可協助您撰寫較少的程式碼來處理 Null 檢查,特別是遞減至資料結構。These operators help you write less code to handle null checks, especially for descending into data structures. 如果左運算元或物件參考為 Null,則作業會傳回 Null。If the left operand or object reference is null, the operations returns null.

多行字串常值Multi-line string literals

字串常值可包含新行字元序列。String literals can contain newline sequences. 您不再需要使用 <xml><![CDATA[...text with newlines...]]></xml>.Value 的舊解決方法You no longer need the old work around of using <xml><![CDATA[...text with newlines...]]></xml>.Value

註解Comments

您可以將註解放到隱含行接續符號之後、初始設定式運算式之內和 LINQ 運算式詞彙之間。You can put comments after implicit line continuations, inside initializer expressions, and among LINQ expression terms.

更聰明的完整名稱解析Smarter fully-qualified name resolution

以程式碼 Threading.Thread.Sleep(1000) 為例,Visual Basic 之前會查詢命名空間 "Threading",發現它在 System.Threading 和 System.Windows.Threading 之間模稜兩可,然後回報錯誤。Given code such as Threading.Thread.Sleep(1000), Visual Basic used to look up the namespace "Threading", discover it was ambiguous between System.Threading and System.Windows.Threading, and then report an error. Visual Basic 現在會同時考慮這兩種可能的命名空間。Visual Basic now considers both possible namespaces together. 如果您顯示完成清單,Visual Studio 編輯器會在完成清單中列出這兩種類型的成員。If you show the completion list, the Visual Studio editor lists members from both types in the completion list.

以年起始的日期常值Year-first date literals

您可以有 yyyy-mm-dd 格式的日期常值 (#2015-03-17 16:10 PM#)。You can have date literals in yyyy-mm-dd format, #2015-03-17 16:10 PM#.

唯讀介面屬性Readonly interface properties

您可以使用讀寫屬性來實作唯讀介面屬性。You can implement readonly interface properties using a readwrite property. 這個介面可確保提供基本功能,並且不會防止實作類別允許設定屬性。The interface guarantees minimum functionality, and it does not stop an implementing class from allowing the property to be set.

TypeOf <expr> IsNot <類型>TypeOf <expr> IsNot <type>

為了增加程式碼的可讀性,您現在可以搭配使用 TypeOfIsNotFor more readability of your code, you can now use TypeOf with IsNot.

#Disable Warning <識別碼> 和 #Enable Warning <識別碼>#Disable Warning <ID> and #Enable Warning <ID>

您可以停用及啟用原始程式檔中區域的特定警告。You can disable and enable specific warnings for regions within a source file.

XML 文件註解改善XML doc comment improvements

撰寫文件註解時,您會取得智慧型編輯器,以及驗證參數名稱、適當處理 crefs (泛型、運算子等)、色彩標示和重構的建置支援。When writing doc comments, you get smart editor and build support for validating parameter names, proper handling of crefs (generics, operators, etc.), colorizing, and refactoring.

部分模組和介面定義Partial module and interface definitions

除了類別和結構之外,您還可以宣告部分模組和介面。In addition to classes and structs, you can declare partial modules and interfaces.

方法主體內的 #Region 指示詞#Region directives inside method bodies

您可以將 #Region…#End Region 分隔符號放到檔案的任何位置及函式內,甚至是橫跨不同的函式主體。You can put #Region…#End Region delimiters anywhere in a file, inside functions, and even spanning across function bodies.

Overrides 定義隱含為 OverloadsOverrides definitions are implicitly overloads

如果您將 Overrides 修飾詞加入定義,編譯器會隱含加入 Overloads,讓您可以在一般情況下輸入較少的程式碼。If you add the Overrides modifier to a definition, the compiler implicitly adds Overloads so that you can type less code in common cases.

屬性引數允許 CObjCObj allowed in attributes arguments

編譯器之前會提供錯誤,指出 CObj(…) 用於屬性建構時不是常數。The compiler used to give an error that CObj(…) was not a constant when used in attribute constructions.

從不同的介面宣告及使用模稜兩可的方法Declaring and consuming ambiguous methods from different interfaces

之前,下列程式碼會產生錯誤,使您無法宣告 IMock 或呼叫 GetDetails (如果已在 C# 中宣告這些項目):Previously the following code yielded errors that prevented you from declaring IMock or from calling GetDetails (if these had been declared in C#):

Interface ICustomer
  Sub GetDetails(x As Integer)
End Interface

Interface ITime
  Sub GetDetails(x As String)
End Interface

Interface IMock : Inherits ICustomer, ITime
  Overloads Sub GetDetails(x As Char)
End Interface

Interface IMock2 : Inherits ICustomer, ITime
End Interface

現在,編譯器會使用一般多載解析規則來選擇要呼叫的最適合 GetDetails,而且您可以在 Visual Basic 中宣告介面關聯性 (如範例所示)。Now the compiler will use normal overload resolution rules to choose the most appropriate GetDetails to call, and you can declare interface relationships in Visual Basic like those shown in the sample.

請參閱See also