Visual Basic .NET (VB.NET )是.NET框架 和後來的.NET 下的一種多重編程範式 高階語言 。
VB.NET,是微軟公司 於2002年作為原有的Visual Basic 的繼承者而推出。雖然自2005年起,語言名稱中的「.NET」就已經被去掉了。但為了與VB 6.0及以前版本的Visual Basic進行區分,「Visual Basic .NET」的名字仍然被社會公眾用來指代VB 7.0及以後的Visual Basic。VB.NET與C# 同為.Net Framework框架下兩種主要的程式語言,都是為了呼叫.Net Framework的類別館資源,因此兩種語言具有很高的對應性,資料類型、控制結構與語言特性都存在一一對應,容易把原始碼從一種語言對譯為另一種語言。
微軟公司的整合式開發環境Visual Studio 是最為廣泛使用的VB.NET開發工具。然而Visual Studio的大部分版本都是價格不菲的商業軟件 ,除了Express版本 和Visual Studio Community (以上兩者皆為免費軟件 )。除了Visual Studio,SharpDevelop 和Mono 也是可用的VB.NET開發環境。
VB.Net的資料類型,實際上是.Net Framework定義的資料類型。
類型名 位元組長度 取值範圍 表示法 Short 2位元組 -32768~32767 number S Integer 4位元組 -2 147 48 3 648~2 147 483 647 number I Long 8位元組 -9223372036854775808 ~ 9223372036854775807 number& numberL Single 4位元組 7位有效數字 num! numberF Double 8位元組 15/16位元有效數字 id# numberR Decimal 16位元組 29位有效數字 id@ numberD Currency 8位元組 小數點右4位元,左15位 number@ Byte 1位元組 0-255 Char 2位元組 UTF-16字元 "d"C DateTime 8位元組 0001-01-01T00:00:00.000 ~ 9999-12-31T23.59.59.999 #4/102008 06:01:23.456 PM# Boolean 2位元組 True(-1) False(0) String UBSTR, 字元數量*2+2 UTF-16字串 "Hello"$ Object 4位元組 Variant
此外,還有SByte、UShort、UInteger、ULong等無符號資料類型。
&O123表示八進制;&H123表示十六進制。
VB使用的名字是大小寫不敏感的。但是,CLR 是大小寫敏感的。所以建議保持一致的大小寫。
VB自版本5以後的資料類型來源於COM ,而其根源是OLE 資料類型。
Nothing(C#的null)表示Object類型的變量(即COM中的IDispatch指標,VB中的所有類和控制項均由IDispatch衍生)為空。對於參照型變量,表示未繫結到一個物理實體對象。 Empty表示VARIANT類型變量未初始化(即COM中的VARIANT結構體中的VT成員值為VT_EMPTY)。 Null表示VARIANT類型變量已初始化,其值為Null,這時COM中的VARIANT結構體中的VT成員值為VT_NULL。通常是所要表示的值不存在或者有問題不合規。實際上,一個參照型變量如果被賦值為Null,則它繫結的地址為0x0000 零長度字串(空字串)需要分配主記憶體,只不過主記憶體(即COM中的BSTR字串)頭4個位元組記錄的長度為0。VB.Net定義了一個Public Shared Readonly Empty As String = ""。對於僅聲明但未實例化的String對象,實際上都繫結到String.Empty對象上。 vbNullString沒有分配數據主記憶體,實際上定義為Dim *vbNullString As String = Nothing。但又規定了字串比較時vbNullString = ""為真。 在與空值做比較時,需要區分各種不同用法:
對象(參照型變量)是否為Nothing,可用IsNothing(對象名),對象名Is Nothing,對象名IsNot Nothing等 在比較資料庫的一個欄位的值是否為空,在.Net中應該用IsDBNull函數或Convert.IsDBNull方法。例如IsDBNull(recordSet("Column1").Value))或者recordSet("Column1").Value=DBNull.Value。因為DBNull是衍生自Object的一個類,DBNull.Value是它的唯一的值。而資料庫中的欄位值,在DataRow中總是表示為Object,永遠不可能為nothing。 比較字串對象是否為空字串,實際上規定了下述三種是等效的:對象名 = "" 對象名 = String.Empty 對象名 = vbNullString 對於可空類型,實際上是Nullable(Of T)泛型結構。例如,下述三行等價:
Dim ridesBusToWork1? As BooleanDim ridesBusToWork2 As Boolean?Dim ridesBusToWork3 As Nullable(Of Boolean) 比較表達式someVar = Nothing的結果永遠是Nothing,應該用someVar.HasValue()方法去判斷是否為空,或者用Is或IsNot關鍵字。
Dim arr ( [ upperLimit ] ) As dataType = new dataType ( [ upperLimit ] ) { [ initialValues ] } '声明数组 arr ( index ) = value '使用数组 陣列的下標開始自0,這遵從了.NET的標準。如果不指定陣列的下標上界,則為動態陣列,其長度可以動態調整。
If 条件 Then 语句 ElseIf 条件 Then 语句 Else 语句 End If Select Case Variable Case Value1 Statements Case Value2 Statements Case Value3 Statements ... Case Else Statements End Select 包括下述幾種:
For varName = 初值 To 终值 [ Step 步长 ] 循环体语句 Next varName Do [ { While | Until } condition ] statements [ Exit Do ] Loop 或
Do statements [ Exit Do ] statements Loop [ { While | Until } condition ] While condition statements [ Exit While ] statemenst End While For Each element in group statements Next [ element ] 實現迭代器遍歷一個序列,每次取得一個返回值。迭代器可以作為一個方法或屬性的get訪問器,其中的Yield 陳述式返回迭代器的返回值,並記住當前執行的位置。下次再呼叫迭代器,從該執行位置恢復執行,直至迭代器代碼執行完或者遇到Exit Function或Return陳述式。編譯器把迭代器作為一個狀態機 的類。
Sub Main () Dim days As New DaysOfTheWeek () For Each day As String In days Console . Write ( day & " " ) Next ' Output: Sun Mon Tue Wed Thu Fri Sat Console . ReadKey () End Sub Private Class DaysOfTheWeek Implements IEnumerable Public days = New String () { "Sun" , "Mon" , "Tue" , "Wed" , "Thu" , "Fri" , "Sat" } Public Iterator Function GetEnumerator () As IEnumerator _Implements IEnumerable . GetEnumerator ' Yield each day of the week. For i As Integer = 0 To days . Length - 1 Yield days ( i ) Next End Function End Class 物件導向時,類的聲明範例:
Public Class className [ Inherits bassClassName ] Public varName As Integer '資料成員 Public [ ReadOnly / WriteOnly ] Property propertyName () As Integer '屬性 Public Get Return m_var End Get Public Set ( ByVal value As Integer ) m_var = value End Set End Property Public Sub subName ( ByVal param1 As Integer ) '方法 End Sub Public Function funcName ( ByVal param2 As Integer ) As Integer '函數 Return 101 End Function [ atrributive_list ][ accessibiliby ][ Shadows ] Event eventName ( [ Parameter ] ) [ Implements interfaces . event ] '事件 Public Sub new ( [ Parameter ] ) '類的構造子(constructor),可以有多個(即可以重載) End Sub End Class 上述範例中的Public關鍵字表示可存取性(accessibility),表示可以被任意代碼存取;它可以替換為其他的可存取性:Private(僅限該Class自身存取)、Friend(僅限同一項目中的代碼存取)、Protected(僅限自身或衍生類別存取)、Protected Friend等。如果使用ReadOnly,則表示資料成員或屬性是唯讀;WriteOnly表示只寫。Shadows關鍵字表示覆蓋父類中同名(但不一定參數相同)的Event。使用關鍵字MyBase參照基礎類別。
類可用繼承修飾詞:NotInheritable關鍵字,表示該類不能做基礎類別;MustInherit關鍵字,表示這是一個抽象類。
類的屬性與方法能否被覆蓋:Overridable關鍵字表示可被覆蓋;Overrides關鍵字表示覆蓋了基礎類別中同名的方法或屬性;NotOverridable關鍵字表示不可覆蓋;MustOverride表示方法或屬性僅聲明沒有實現,這時該類必須有MustInherit修飾詞,是一個抽象類或者介面,僅能包含屬性、方法、函數的聲明。
如同其他.Net語,Visual Basic不允許多重繼承,但可以同時實現多個interface。
介面是一類特殊的抽象類,不能包括可執行代碼與類的資料成員的聲明:
Interface interfaceName Event eventName ( [ param ] ) Property [ ReadOnly / WriteOnly ] propertyName As typeName Function funcName ( [ param ] ) As returnTypeName End Interface 介面中這些成員都強制是Public可存取性。
實現一個介面,使用Implements關鍵字:
Public Function GetEnumerator () As IEnumerator _Implements IEnumerable . GetEnumerator 基於繼承的多型 ,是指用基礎類別類型的變量繫結不同的子類別物件,這樣呼叫基礎類別變量的方法,在執行時 動態確定實際執行了哪個衍生類別的同名的方法。多型的優點是可以針對基礎類別(或介面)的方法來寫一個通用的過程或者資料容器,適用於各種不同的衍生類別的具體實現。
委託本質上是一種Class,衍生自System.Delegate,包含了三部分資料:一個類物件的地址、該物件所屬類的一個方法的地址,以及另一個委託的參照(reference)。前兩部分可以實現對一個類物件的方法的呼叫;第三部分把委託形成一個連結串列,使其依次被呼叫執行。如下聲明了一個委託:
Delegate Sub PlayHandler(ByVal sender As Object, ByVal e As System.EventArgs) 委託常用於事件處理(Event Handler)。.Net Framework 的事件是類的屬性(實際上是一個巢狀類),用於封裝參數格式固定的委託;該委託的參數總是為(ByVal sender As Object, ByVal e as System.EventArgs),返回值為void(即Sub類型)。例如:
Public Class clsName Public Event monitor As PlayHandler End Class 對一個具體的實例,可以給它的事件在運行時動態追加上一個或多個事件處理函數:
AddHandlerins.monitor, AddressOf playHandle_1 AddHandle指向引發事件的對象;AddressOf把一個函數或過程名轉化為一個隱式創建的委託實例,用於確定該事件物件所要呼叫的事件處理程式。在AddressOf關鍵字可隱式創建一個參照特定過程的委託的實例。
程式可以投擲一個事件:
Dim WithEvents e As New System.EventArgs Dim ins As New clsName RaiseEvent ins.monitor(ins,e) using陳述式,定義一個範圍,在範圍結束時自動釋放對象所佔用的資源。
Using conn As New SqlConnection'當在某個代碼段中使用了類別的實例,而希望無論因為什麼原因,只要離開了這個代碼段就自動呼叫這個類別實例的Dispose。 '執行代碼End Using 例如:
Public Property pa As String="" 集合(Collection)對象的初始化與普通類對象的屬性初始化,分別使用From與With關鍵字。例如:
Public Class Person Public Property age As Integer Public Property Name As String End Class Dim personList As New List ( Of Person ) From { New Person With {. Name = "Qiang" , . age = 24 }, New Person With {. Name = "Wei" , . age = 42 } } 例如:
Dim people = New With {.name="kyo", .age=22} 即無名的函數或過程,作為表達式的值。可以寫為一行或多行。例如:
Dim func1=Function(i As integer) i+10Dim action = sub() End SubDim func2 = Function() End Function 可以在聲明匿名函數的同時呼叫它。單行的lambda表達式不能使用Return關鍵字,其返回類型是自動推導得出;其參數要麼都是用As關鍵字指明類型,要麼全部是自動推導出類型。
lambda表達式在定義時可以使用所在上下文(context,即C++語言的閉包closure)的局部變量、參數、屬性、Me等等的值,即使lambda表達式離開了定義時所在的context,這些被使用的局部變量等的值仍然有效。這是因為lambda表達式在定義時把所用到的context的值儲存到它自己的定義類中。lambda表達式可以巢狀定義。
例如:
Imports System.Runtime.CompilerServices<Extension()> Public Function funcName(ByVal ins As className) As String 'Do somethingEnd Function Try ' write the condition here Catch ex As Exception When condition ' Handle Exception when a specific condition is true Catch ex As Exception ' Handle Exception Finally ' Cleanup, close connections etc ' NB this code is always executed regardless of if an Exception was raised or not! End Try From element [ As type ] In collection [, element2 [ As type2 ] In collection2 [, ... ] ] [Where 表达式] 這裏給出了一個Hello World的例子。通過它們您可以更好地理解Visual Basic的特性。(此原始碼執行於命令列下)
Module Mdl_Main Sub Main () Console . WriteLine ( "Hello World" ) End Sub End Module 這個程式能輸出Hello World 。
第一行是模組定義,命名空間的定義一般可以省略。VB.NET中,所有函數,過程與變量的聲明都必須在模組或者類的內部,而不能直接存在於命名空間內部。
第二行定義了名為Main的過程。一般來說,「Sub Main()」是程式的入口點。
Console . WriteLine ( "Hello World" ) 第三行輸出「Hello World」。
第四行結束了過程Main的定義。
第五行結束了模組Mdl_Main的定義。
與舊版VB (VB 6.0及以前)相比較,VB.NET明顯受到了.Net Framework中其他語言思想的影響。與舊版VB相比,VB.NET更加嚴格而不失靈活。
Long類型與Integer類型的長度分別倍增,達到了64位元和32位元。事件 的處理過程不再依賴於名稱,而是通過Handle子句進行靜態繫結或者在執行時進行動態繫結。例如處理按鈕控制項Button1的Click事件:Visual Basic 6:(注意此過程的名稱不可改變)
Private Sub Button1_Click () 'Work to do End Sub VB.NET:(注意此過程的名稱無關緊要)
Private Sub Button1_Click ( ByVal sender As Object , ByVal e As EventArgs ) Handles Button1 . Click 'Work to do End Sub 很多原有的實現特殊功能的陳述式被相應定義好的函數替代。這減少了關鍵字的使用(如Open()函數取代Open陳述式,表單的Print()方法取代Print陳述式)。同時,被封裝好的、功能更強大的、通用於.Net Framework框架的類被推薦用來取代原有的陳述式。 對一些更強大的語法特性的支援,如:LINQ ,Lambda表達式 (Visual Basic 2010起支援多行Lambda)。 同樣使用:作為一行中分行的符號,_作為續行符。但是VB.NET自Visual Basic 2012起允許在函數的定義與呼叫中不加_地用換行分隔各個參數。 與C家族語言相比,VB.NET則較多保留了VB的特徵,比如:
與C家族語言統一使用{、}定義陳述式塊不同,VB.NET每種陳述式塊都有對應的開頭與結尾。如If ... Else ... End If,Class ... End Class。 VB.NET定義變量使用Dim關鍵字,同時使用Public、Private或Protected表明範疇時可以省略Dim。 VB.NET表示變量類型的方式是在變量名後附加As Type(Type為變量類型),而C家族語言是在變量名之前書寫類型名,無論在定義變量時還是在函數與形參的聲明時都是這樣。 VB.NET中有沒有返回值的特殊子過程Sub。VB.NET中沒有void類型,C#中返回值為void的函數對應了VB.NET中的Sub。 VB.NET中有一種特殊的類型Module,相當於C#中的static class。 下面這兩份功能一致的代碼展現出了VB.NET與C#的很多不同之處:
Namespace N 'Comment Module M Public Function GetSum ( arr () As Integer ) As Integer Dim Sum = 0 'Auto Type Infer Dim i As Integer For Each i In arr Sum += i Next Return Sum End Function End Module Class C Private v As Integer Public Function F () As Integer Return v * v End Function Public Sub S ( value As Integer ) Me . v = value End Sub Public Sub New () 'Constructor Me . v = 0 End Sub End Class End Namespace namespace N { //Comment static class M { int GetSum ( int [] arr ) { var Sum = 0 ; int i ; foreach ( i in arr ) { Sum += i ; } return Sum ; } }; class C { private : int v ; public : int F () { return v * v ; } void S ( int value ) { this . v = value ; } C () //Constructor { this . v = 0 ; } }; } VB.NET與C#同為.Net Framework的兩大主力程式語言,儘管有着各種各樣的不同,兩者最終都編譯為MSIL 並由CLR 執行。兩者功能基本一致,並可以在.Net Framework框架下方便地互相呼叫與協同開發。關於兩者的優劣一直見仁見智。
C語言編寫的DLL檔案,VB在呼叫時,需要注意:對於C語言的陣列指標,在VB中呼叫時應將陣列的首元素傳遞給DLL。不能直接傳遞陣列名,因為如果傳遞陣列名,VB實際會傳一個複雜的結構類型給DLL。C函數無法確定陣列大小,通常用另一個參數指出陣列的大小。
<DllImport("D:\GenericMESDLL.dll", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.Cdecl)> Public Sub test ( ByVal param As Integer , ByRef OK As Integer ) End Sub '下述方法只能使用_stdcall调用约定: Public Declare Function test1 Lib "D:\PackingDLL.dll" Alias "_test@4" ( ByVal param As Integer ) As Integer 2002年Visual Basic .NET(VB 7.0)[ 編輯 ] Visual Basic .NET(VB 7.0)是隨Visual C#和ASP.NET一起在2002年發布的最初始的VB.NET版本。C#被大力宣傳為微軟對付JAVA的王牌,受到媒體極力關注。然而VB.NET(有時被稱為VB 7.0)影響面不廣,這導致VB社區之外很少人關注它。那些試用過此版VB.NET的人在層層幕布下發現一個強大卻艱深的語言,而且還有不少缺點,例如它的執行階段組件(Run-Time)比VB6大了十倍,記憶體使用量也大大增加。
VB 7.0引起了廣泛的爭議,主要原因在於對舊版VB的改動過大。許多資深的VB程式設計師抱怨VB.NET,因為VB.NET 2002丟掉了許多不再發行的VB6中使用的大量語言結構和用戶介面功能,並且對保留下來的東西也改變了語意。例如,在VB.NET參數預設是以值方式傳遞的,而不是以參照方式。VB.NET 2002被半嘲諷半認真地稱為Visual Fred或VB DOTNOT。作為對2005年3月8日微軟拒絕為VB6再提供維護與支援的回應,當月月底出現了反對者的請願[ 6] 。
VB.NET的支持者們認為新語言在很多方面比舊版本更為強大,比如它以相比早期版本更為自然、緊密和完全的方式地加入了現代物件導向的編程範式。反對者們有不同意見,雖然VB6對對象模型支援有缺點,但是二次開發升級到VB.NET的成本比升級後的收益要高得多。而開發軟件發布互聯網版本的獨立程式設計師也對VB.NET的RunTime尺寸過大不滿。
針對開發者的不滿,微軟主要做了如下努力:使新的開發更容易啟動,而把已經開發的VB6代碼升級到VB.NET[ 7] 。例子主要包括:完成VB6中的常見任務如預覽列印;整合VB6和VB.NET解決方案(dubbed VB Fusion),從VB6代碼轉換到VB.NET。
微軟在後續版本中復原了一些過激的更改,並且吸取了經驗。在以後版本中,語法的更改變得更加謹慎。
2003年Visual Basic .NET 2003(VB 7.0)[ 編輯 ] Visual Basic .NET 2003(VB 7.0)和.NET Framework 1.1一起發布。新功能包括對.NET Compact Framework的支援和更好的VB升遷精靈。並改進了執行狀況,IDE穩定性(尤其是後台編譯器),以及執行時RunTime穩定性。另外,VB.NET 2003還有一個學院版Visual Studio .NET 2003 Academic Edition(VS03AE),它是分發給各國某些學者免費使用的版本。
2005年Visual Basic 2005(VB 8.0)[ 編輯 ] Visual Basic 2005(VB 8.0)是VB.Net的重大轉變,微軟決意在其軟件名稱中去掉了.NET部份。在VB2005中,微軟增加了許多新功能,以參照VB對於初學者來說的一些優點:
主要的變動:
不再支援「Edit and Continue」 - 早期Visual Basic可以在除錯時修改代碼並且不經重新編譯地執行。Visual Basic 2005去掉了這個功能; 設計時錶達式求值; 提供My偽命名空間,包含了不需大量編碼而訪問特定.NET Framework功能的簡單方式;提供了改進的VB到VB.NET轉換精靈;Using語法,簡化了需要部署pattern to free resources的對象的使用;My編碼,可隱藏由VB.NET IDE寫的模板代碼;數據源繫結,簡化了資料庫C/S開發。上述功能(尤其是My)增強了VB.Net成為快速開發應用平台的可能,並與C#進一步區別開來。Visual Basic 2005通過增加新功能而減小了和其它所謂更強大的.NET語言的差距。 增加了.NET 2.0語言功能包括:泛型 (generics)和Partial類(在一個檔案里定義一個類的某部份然後在另外的檔案里添加更多的定義,這個方法在整合用戶書寫的代碼和系統自動生成的代碼時尤其有用); XML註釋,可以被NDoc等工具處理而自動生成文件; 運算子多載; 支援在其它語言中已經廣泛使用的unsigned integer 資料類型; 支援在許多C衍生程式語言已提供的複合運算子如:"+=", "-="; IsNot專利:If Not X Is Y表達式被轉換成If X IsNot Y。當微軟為IsNot申請專利時招致了惡名(尤其來自Real公司); Visual Basic 2005 Express:作為VS產品線上的一部份,VB2005 Express是專為業餘愛好者和新手客製化的免費的VS Express系列的一員。Express版本目的定位在幫助人們學習一種語言,所以他們有和標準版一致的用戶介面,只是少了一些進階功能。另外,VS Express版包括了VB6.0轉換器,提供了從VB老版本升級的可行方法。 2008年Visual Basic 2008(VB 9.0)[ 編輯 ] Visual Basic 2008(VB 9.0)於2007年11月9日與Microsoft .NET Framework 3.5一起發布。
在VB2008中,微軟增加了許多功能,包括:
IIF函數 匿名類型 支援LINQ Lambda表達式 XML數據結構 類介面 2010年Visual Basic 2010(VB 10.0)[ 編輯 ] Visual Basic 2010於2010年4月發布。
2012年Visual Basic 2012(VB 11.0)[ 編輯 ] 2013年Visual Basic 2013(VB 12.0)[ 編輯 ] 2015年Visual Basic 2015(VB 14.0)[ 編輯 ] Visual Basic 2015(VB 14.0)於2015年7月20日發佈。
2017年Visual Basic 2017(VB 15.0)[ 編輯 ] 2019年Visual Basic 2019(VB 16.0)[ 編輯 ] 2022年Visual Basic 2022(VB 17.0)[ 編輯 ] [ 8] 2022 年 9 月 13 日 - Visual Studio 2022 17.0.14版 NewReleaseIcon
2022 年 8 月 9 日 - Visual Studio 2022 17.0.13版
2022 年 7 月 12 日 - Visual Studio 2022 17.0.12 版
2022 年 6 月 14 日 - Visual Studio 2022 17.0.11版
2022 年 5 月 10 日 - Visual Studio 2022 17.0.10 版
2022 年 4 月 19 日 - Visual Studio 2022 17.0.9版
2022 年 4 月 12 日 - Visual Studio 2022 17.0.8版
2022 年 3 月 8 日 - Visual Studio 2022 17.0.7 版
2022 年 2 月 8 日 - Visual Studio 2022 17.0.6版
2022 年 1 月 13 日 - Visual Studio 2022 17.0.5 版
2021 年12 月 16 日 - Visual Studio 2022 17.0.4版
2021 年 12 月 14 日 - Visual Studio 2022 17.0.3 版
2021 年 11 月 30 日 - Visual Studio 2022 17.0.2版
2021 年 11 月 16 日 - Visual Studio 2022 17.0.1版
2021 年 11 月 8 日 - Visual Studio 2022 17.0.0 版
實作 架構 共同語言基礎架構 CLI支援語言
Core家族3 元件 比較 即將推出