综述: 这篇文章为计划将他们的应用程序更新到Visual Basic.NET的微软Visual Basic 开发用户提供一些建议。它包括有关Visual Basic.NET 更新工具的一些信息,并讨论了使应用程序稳定地从Visual Basic 6 更新到 Visual Basic.NET的总体结构指导思想.
目录
为什么 Visual Basic.NET 不是 100% 兼容的?
同时使用 Visual Basic 6.0 和Visual Basic.NET
概述
这篇文章是为准备更新Visual Basic到Visual Basic.NET的使用Microsoft Visual Basic的用户提供一些建议。
Visual Basic.NET将打开并将Visual Basic 6.0项目更新到Visual Basic.NET技术,但是在大多数情况下,在你把Visual Basic 6.0的项目调入Visual Basic.NET之前必须做一些修改。这篇文章的目的是建议你如何设计和执行你现有的Visual Basic项目,使得你在更新到Visual Basic.NET时需要做的修改最小化,在最合适的地方使用新的语言结构;然而这篇文章却不是Visual Basic.NET语言的参考书.
注意:Visual Basic.NET 仍然在开发之中;一些兼容性细节在产品发布以前还可能会改变。遵循这些指导原则并不能保证你的代码不再需要修改;相反这个指导的目的是减少这种转变的工作量。
Visual Basic.NET中的更新向导和命令行更新工具仍然在早期的开发阶段,因此它们的功能是有限的。在Beta版中包括这些功能的目的是让你知道更新过程是如何工作的,看看如何修改VB6.0代码以便它们能在Visual Basic.NET中工作;在Beta1版中,大多数实际项目或许是不能成功移植的。
什么是 Visual Basic.NET?
Visual Basic.NET是Visual Basic的下一个版本。微软不是简单的在Visual Basic 6.0的基础上增加了一些新特性,而是重新更换定制了这个产品,从而使得编写分布式的应用程序,例如网页和企业n层系统,比以前更简单了。Visual Basic.NET有两个新的窗体包(Windows 窗体和网页窗体);一个用于无连接数据源的新的ADO版本;改进的语言,去处了继承关键字,增强了类型安全性,和高级开发者需要的低级结构。
这些新的特点为Visual Basic开发者打开了新的门户;使用网页窗体和ADO.NET,你现在可以快速开发可扩展的网站;使用继承,这个语言现在真正支持面向对象编程;Windows窗体天然地支持可访问性和可视化继承特点;现在部署你的应用程序非常简单,只需要将可执行文件从一个目录拷贝到另一个目录。
Visual Basic.NET 现在已经与Microsoft Visual Studio.NET 其他的几种语言完全综合在一起了 。你不仅可以用不同的编程语言来开发应用程序组件,现在你的类使用交叉语言继承还可以从其他语言编写的类中继承而来。使用统一的调试器,你现在可以调试多语言应用程序,而不管它们运行在本地机上还是在远程计算机上。最后,无论你使用什么语言,微软.NET框架为Microsoft Windows和因特网提供了丰富的API接口函数。
为什么 Visual Basic.NET 不是 100% 兼容的?
在设计Visual Basic.NET的时候考虑到了两种选择--翻新源代码基础使之在.NET框架上运行,或是从基础做起充分利用平台。为了交付客户最需要的特点(例如:继承,线程等),为了提供完全的无限制的访问平台,为了使Visual Basic进入下一代网络应用程序,正确的决定是:从基础创建一个新的平台。
例如,大多数Windows窗体的新特征可以作为新控件和更多属性加入到现有的基础代码中。然而,这样做的代价是放弃了继承到Windows窗体的其它更多特性,如:安全性,可视继承特性等。
我们最主要的目的之一是保证Visual Basic代码能够与其它语言,如Microsoft Visual C# 或 Microsoft Visual C++编写的代码完全交互,使Visual Basic开发者能简单地利用.NET Framework的功能,而不是求助于传统的需要处理Windows API函数的编程环境。Visual Basic现在具有和Visual C++和其它语言相同的变量类型,数组,用户定义类型,类和接口,目的是公共语言运行时间(Common Language Runtime);然而,我们不得不去处一些特点,如固定长度字符串和非零地址数组等。
Visual Basic现在是一种真正的面向对象语言;一些象GoSub/Return和DefInt等非直觉的和不一致的特点已经从这种语言中去出了。
结果是产生一个重新加强的Visual Basic,它继续是开发基于Windows的应用程序的多产工具,现在定位于创建下一代网站的最好工具。
更新到 Visual Basic.NET
Visual Basic.NET 完成了由传统的Windows开发到创建下一代网页和n层应用程序的重大转变。因为这个原因,你的代码就需要更新来充分利用Visual Basic.NET。
当你在Visual Basic.NET 中打开一个Visual Basic 6.0项目时,此过程自动执行:更新向导一步一步引导你完成更新过程,并建立一个新的Visual Basic.NET项目(你原来的项目仍然完好存在)。这是一个单向的过程;Visual Basic 6.0中不能打开Visual Basic.NET的项目。
当你的项目在更新时,由于一些语法的改变会修改代码并且 Visual Basic 6.0窗体都变成Windows窗体。在大多数情况下,更新之后你必须对你的代码作一些修改。这是因为自动更新中某个对象和语言特点在Visual Basic.NET并没有完全等价的,或等价之处有太多的不同之处。更新之后,你也会想通过改变你的应用程序来更好的利用Visual Basic.NET的一些新特点。
例如:Windows窗体支持控件入坞,所以你可以去除Visual Basic6.0中的窗体来重新编程。
VB.NET 支持控件入坞
在你的项目完成更新之后,为了帮助你做这些修改,Visual Basic.NET给你的项目增加了一个"更新报告",详细说明了每个问题,并在你的代码中插入了注释,向你提示这些代码需要修改。由于这些注释在新的任务列表窗口显示为需要做的任务,你能很容易看出哪些需要修改,并且通过双击任务可以很容易找到相关的代码。在更新报告中的每个任务和项目与在线帮助连接在一起,相关主题将会给你诸如为什么这儿代码需要修改,你需要做什么等进一步的指导。
遵循这篇文章的建议,你能使得你的项目在更新到Visual Basic.NET之后需要做的工作最小化,在一些情况下,甚至可以消除这种必要的修改。在大多数情况下,这种建议也代表了好的编程习惯;但是,我们也认识到对象和方法Visual Basic.NET中没有等价物,如果你想更新你的项目到Visual Basic.NET中,你就必须少用他们。
同时使用 Visual Basic 6.0 和Visual Basic.NET
Visual Basic.NET 支持更新的 Visual Basic 6.0 项目;如果你的项目是Visual Basic1-5版本的,我们推荐你在更新到Visual Basic.NET以前首先装入到Visual Basic6.0(选择更新Microsoft ActiveX控件),编译并保存。
Visual Basic.NET 和 Visual Basic 6.0能够同时安装在一台计算机上并能同时运行。同样的,用Visual Basic.NET 和 Visual Basic 6.0编写的程序也能安装在同一台计算机上同时运行。在Visual Basic.NET 写的组件能够和Visual Basic 早期版本或其它语言编写的COM组件混合使用。例如,你可以把一个Visual Basic 6.0中编写的ActiveX控件放在Visual Basic.NET Windows窗体之上,可以使用来自Visual Basic.NET类库的Visual Basic 6.0 COM对象,或将一个Visual Basic.NET库连接增加到Visual Basic 6.0的可执行文件中。
用Visual Basic.NET编译的组件和用Visual Basic 6.0编译的组件在运行时有一些微妙的不同,因为Visual Basic.NET对象释放是通过碎片收集完成的,当对象明确被销毁时,在从内存里完全删除以前要有一段延迟。还有一些诸如变体和对象的变化在这篇文章的后面将有所描述。这些不同之处结合地结果是Visual Basic.NET应用程序与Visual Basic 6.0应用程序具有相似性但在运行时的行为又不完全相同。
另外,Visual Basic.NET使得Visual Basic.NET组件和Visual Basic 6.0组件之间的二进制兼容性完全没必要。现在组件已经有了比以前更健壮的版本和开发系统。文件的部署可以通过简单的拷贝到目录中(而不再是使用RegSvr32),组件更新到一个新的版本如同一个新的文件代替一个旧的文件一样简单。你所要做的就是要保证类和方法与前一个版本兼容。
体系结构推荐
.NET平台改善了以前的体系结构,大量增加了对扩展性和通过离散数据访问的分布式应用程序的支持,基于HTTP的信息传递和基于文件拷贝的配置(不再注册组件)的支持。为了充分利用这些特征,你应该用与Visual Basic.NET中使用的结构相似的结构设计你的应用程序。
基于基于浏览器的应用程序
Visual Basic 6.0 和 Microsoft Visual Studio 6.0提供好几种技术来创建基于浏览器的因特网和内部网络的应用程序:
网页类
DHML项目
ActiveX文档
活动服务器网页(ASP)
Visual Basic.NET引入了ASP.NET,它是ASP的一个加强版本,并且在结构中增加了网页窗体,它是具有Visual Basic事件的HTML页。这种体系结构是基于服务器的。
以下是一系列开发Visual Basic 6.0基于浏览器应用程序(这些应用程序能够和Visual Basic.NET项目无缝结合)的推荐和体系结构建议。
我们加以你使用微软中间层体系结构指导原则来创建你的应用程序,创建ASP接口,并使用Visual Basic 6.0或Visual C++ 6.0 COM对象来组成你的企业逻辑。ASP在Visual Basic.NET中是完全支持的,你可以继续使用ASP和ASP.NET扩展你的应用程序和网页窗体。Visual Basic 6.0 和 Visual C++ 6.0企业对象不需要修改或更新到Visual Studio.NET就能使用。
DHTML应用程序包DHTML页和客户端DLL。这种应用程序不能自动更新到Visual Basic.NET。我们建议你不用更新这一类型的应用程序,继续留在Visual Basic 6.0中。
ActiveX文档在Visual Basic.NET也是不支持的,和DHTML项目一样,是不能自动更新的。我们推荐你要么不用更新这一类型的应用程序,继续留在Visual Basic 6.0中,或如果可能使用用户控件代替ActiveX文档。
Visual Basic 6.0 ActiveX文档和DHTML应用程序能够和Visual Basic.NET技术交互操作。例如,你能够通过Visual Basic.NET的网页窗体到Visual Basic 6.0的DHTML网页,反之亦然。
网页类在Visual Basic.NET中已经不再存在了。网页类的应用程序将被更新到ASP.NET中;然而,你将在更新之后不得不做一些必要的修改。现有的网页类应用程序与Visual Basic.NET地网页窗体和ASP应用程序交互操作,但是对于一个新的项目,我们建议你使用ASP的Windows DNA 平台和Visual Basic 6.0企业对象。
想了解使用微软中间层体系结构创建应用程序的更多信息,看Microsoft Windows DNA网站。
客户/服务器项目
Visual Basic 6.0提供几种技术来创建客户/服务器应用程序:
Visual Basic窗体
微软事务处理服务器(MTS)/ COM+中层对象
用户控件
在Visual Basic.NET中,有一个新的社会窗体包:Windows窗体。Windows窗体具有与Visual Basic 6.0窗体不同的对象模型,但是大致来说是兼容的。当你的项目师更新时Visual Basic窗体被转变为Windows窗体。
Visual Basic.NET提高了对开发中间层MTS 和COM+组件服务组件的支持。使用统一的调试器,你可以从客户应用程序进入MTS/COM+组件并回到客户端。你也能够通过使用统一的调试器进入Basic 6.0 MTS/COM+组件(倘若他们把本地代码和符号调试信息和非最优化编译连接)。
Visual Basic.NET也引入了一个中间层组件:网页服务。网页服务寄存在ASP.NET中,并且通过使用HTTP传输允许方法请求通过防火墙。他们通过工业标准XML传递、返回数据,允许其它语言和其它平台来访问他们的函数。尽管他们不支持MTS传输,在你不需要分布式处理但是想与其他平台交互的情况下,你可以改变你的MTS/COM+组件到网页服务。尽管对他没有自动的方法,但是这个任务简单,在更新到Visual Basic.NET之后几分钟之内使用拖拉操作就能完成。
当你的项目更新时,用户控件更新到Windows控件;然而定制属性标签设置和加速键分配是不能更新的。
单层应用程序
Visual Basic 6.0支持创建多种类型的单层应用程序:
单层数据库应用程序
Visual Basic插件
应用程序和游戏软件
单层数据库应用程序典型的情况是Visual Basic应用程序在微软Access数据库中存储数据。这些应用程序要更新到Visual Basic.NET具有一些局限性(见后文数据章节)。
既然Visual Basic.NET集成开发环境完全集成在Visual Studio.NET集成开发环境中,Visual Basic.NET具有一个新的语言中立的扩展模块。Visual Basic.NET插件现在是Visual Studio.NET的插件,你可以在Visual Studio.NET中自动加入一些特点到任何语言。例如,你可以写Visual Basic.NET插件,这个软件完成在Visual C#中对Windows窗体重新着色或给Visual Basic类附加注释。为了增加这种功能,Visual Basic.NET放弃了过去可扩展的模块,你将需要在你的应用程序中改变可扩展性对象以充分利用这些新特点。
许多应用程序都可以归入实用程序类中。实用应用程序处理文件,设置注册表等等,并经常不需要额外变化就能完成更新。更新之后,你就可以充分利用很多新的特性,如除了语言中的例外处理以捕获文件系统错误,使用.NET框架注册类来操作注册表。我们应该意识到的是依赖于Visual Basic 6.0特殊的运行特征的应用程序,例如娱乐游戏,可能将需要一些修改,因为Visual Basic.NET具有不同的运行特性。在Visual Basic.NET对游戏的支持,使你能够使用Microsoft DirectX 7或GDI新版本。GDI+引入了许多新特点,包括Alpha绑定对2-D图形支持既反别名和对印象文件格式的支持。
数据
Visual Basic 6.0提供几种数据访问类型:
ActiveX(ADO)数据对象
远程数据对象(RDO)
数据访问对象(DAO)
Visual Basic.NET引入了增强的ADO版本,称为ADO.NET。ADO.NET把目标定位于离散数据并在分布式应用程序中提供改进的ADO。ADO.NET为Windows窗体的控件提供读写数据绑定,为网页窗体提供只读数据绑定。
DAO, RDO, 和ADO经过略微的修改在Visual Basic.NET的代码中仍然可以使用的(本文稍后在语言章节中会提到)。然而,Visual Basic.NET中不支持DAO 和RDO将数据绑定到控件,数据控件或RDO用户连接。我们建议,如果你的应用程序包括RDO和DAO数据绑定控件,你要么不用更新,要么在更新到Visual Basic.NET之前更新到DAO和RDO数据绑定到ADO,因为ADO数据绑定在Windows 窗体中支持ADO数据绑定。关于如何做请参考Visual Basic 6.0的帮助文件。
总之,我们建议在Visual Basic 6.0的项目中使用ADO。
更新
当你的代码在更新时,Visual Basic.NET产生一个更新的项目,并为你产生必要的语言和对象的转变。以下章节中为你提供一些例子,说明如何更新你的代码。
变体到对象
在Visual Basic早期版本中支持Variant 的数据类型,它可以分配给简单的任何类型(除了定长字符串),空字符串,零和Null.在Visual Basic.NET中,变体和对象的功能合并为一种新的数据类型:对象。对象数据类型分配简单的数据类型,空数据,无,和Null,甚至一个指向对象的指针。
当你的项目更新到Visual Basic.NET时,所有声明为Variant的变量改变为对象,同时,在代码插入编辑器的时候,关键字Variant也由Object代替了。
整型到短整型
在Visual Basic.NET中,16位的数字现在成为Short(短整型),32为的数字被成为Integer(整型)(64位成为Long(长整型)。当你的项目在更新时,这些数据类型改变了。
Dim x As Integer
dim y as Long
被更新为:
Dim x As Short
dim y as Integer
属性语法
Visual Basic.NET中为属性引入了更直观的语法,划为Get 和Set类。你的属性描述更新有如如下例子:
Property Get MyProperty() As Integer
MyProperty = m_MyProperty
End Property
Property Let MyProperty(NewValue As Integer)
m_MyProperty = NewValue
End Property
更新为:
Property MyProperty() As Short
Get
MyProperty = m_MyProperty
End Get
Set
m_MyProperty = Value
End Set
End Property
Visual Basic窗体到Windows窗体
Visual Basic.NET有了一个新的窗体包,Windows窗体,它天然支持访问特性,并有一个本地菜单编辑器。你的Visual Basic窗体将被更新为Windows窗体。
图2. Windows 窗体放置的菜单编辑器. (单击图片可以看到更大的图象)
接口
在Visual Basic的早期版本中,公用类的接口通常是对用户是不可见的。在Visual Basic.NET中,在代码编辑器中可以查看并对其进行编辑。当你的项目在更新的时候,你可以选择是否为你的公共类自动产生接口声明。
更新报告和注释
你的项目更新之后,在你的项目中增加了一个更新报告,详细说明了在你更新的代码中需要修改的地方。另外,在你的代码中加入的注释警告你一些潜在地问题。这些注释在Visual Studio.NET的任务列报中列了出来。
图3. 在Visual Basic 代码中增加了更新注释,也增加了任务列表中 (单击图象可以看到更大的图象) 编程建议
这一节中为如何编写代码,才能使你的项目更新到 Visual Basic.NET之后需要做的修改最小化方面提出一些建议。
使用早期绑定
Visual Basic 6.0 和 Visual Basic.NET 都支持晚期绑定对象,其实际作法是,将一个变量声明为Object数据类型,然后在运行时刻为其分配一个实例。然而,在更新过程中,晚期绑定对象在解析缺省属性或在底层对象模块发生了变化并且属性,方法,和事件需要改变的时候,它就会引入一些问题。例如,假如你有一个带有标签为Lable1的窗体Form1,如下Visual Basic 6.0代码将标签设置为"SomeText":
Dim o As Object
Set o = Me.Label1
o.Caption = "SomeText"
在Visual Basic.NET Windows窗体中,Label控件的Caption属性现在叫做Text。当你的代码更新时,所有实例的Caption属性将全部转变为Text,但是由于晚期绑定的对象的类型不定的,即便是一些特性能够被翻译出来, Visual Basic不能检测到对象的类型。在这种情况下,你应该在代码更新完成之后,自己修改代码。
如果你用早期绑定对象来重新编写代码,它将自动更新:
Dim o As Label
Set o = Me.Label1
o.Caption = "SomeText"
你应该在可能的地方声明任何合适的对象类型的变量,而不是简单的生命为对象(Object)数据类型。
当在你的Visual Basic 6.0代码中使用了对象和变体变量,当你在分配变量,对变量执行操作或者向一个函数传递一个变量时,我们建议你使用明确的转化。例如,'+'操作符的目的在下面代码中不很直接:
Dim Var1 As Variant
Dim Var2 As Variant
Dim Var3 As Variant
Var1 = "3"
Var2 = 4
Var3 = Var1 + Var2 'UNCLEAR: What is the intention?
Var1和 Var2是作为字符串相加呢,还是整数相加呢?
上面例子在Visual Basic.NET中可能会产生运行错误。使用明确地转化重新编写最后一行代码,以保证代码工作:
Var3 = CInt(Var1) + CInt(Var2) 'GOOD: explicit conversion
Visual Basic.NET 支持基于参数类型的重载函数。例如:
Environ( Expression As Integer) As String
Environ( Expression As String ) As String
Visual Basic.NET根据参数决定调用哪一个函数。如果你传递一个整数参数给Environ(),将调用整数版本的函数;如果你传递字符串,则调用的是字符串版本的函数。传递变体或对象数据类型给重载函数可能会引起编译或运行错误。使用直接的转化,如下例子,在你的代码更新之后在Visual Basic.NET正常工作。
Dim a As String
Dim v As Variant
v = "Path"
a = Environ(CStr(v)) 'GOOD: explicit conversion
明确转换晚期绑定对象的是一个良好编程习惯。这样使得代码的目的很容易判断,也很容易使你的代码移植到Visual Basic.NET 中。
使用Date存储日期
早期版本的Visual Basic支持使用Double数据类型来存储和处理日期。在Visual Basic.NET中你不应该这么做了,因为数据是不能作为Double来存储的。例如,如下代码在Visual Basic 6.0中使有效的,但是在Visual Basic.NET中可能会引起编译错误。
Dim dbl As Double
Dim dat As Date
dat = Now
dbl = dat 'VB.NET: Double can't be assigned to a date
dbl = DateAdd("d", 1, dbl) 'VB.NET: Can't use Double in date functions
dat = CDate(dbl) 'VB.NET: CDate can't convert double to date
.NET平台提供ToOADate 和FromOADate函数来完成双精度数据和日期型数据间的转化。然而,当你的项目更新到Visual Basic.NET时,决定那些用双精度数据来存储日期的代码的含义就变得非常困难了。为了避免在Visual Basic.NET中修改你的代码,请使用日期型数据类型来存储日期。
处理无参缺省特性
在Visual Basic 6.0中,许多对象显示出缺省的特性,在编程中省略它们是一种编程捷径。例如TextBox有一个缺省的特性Text,所以缺省写法:
MsgBox Form1.Text1.Text
你可以使用简单方法:
MsgBox Form1.Text1
缺省属性的判断是在代码编译时完成的。另外,你可以按照如下例子使用晚期绑定对象的缺省属性:
Dim obj As Object
Set obj = Form1.Text1
MsgBox obj
在晚期绑定例子中,缺省属性在运行时才作决定的,MsgBox显示的TextBox的缺省属性的值是Text1。
Visual Basic.NET不支持无参缺省属性,从而也不支持这种编程捷径。当你的项目更新时,Visual Basic.NET解析这些无参缺省属性,但是在运行时才能解析的晚期绑定控件是不能自动解析的。在这些情况下,你将不得不自己来修改代码。更麻烦的是许多库中使用了_Default来实现缺省属性的。_Default就像是一个代理,将调用传递到真正的缺省属性。所以,当你的项目在更新时,一些缺省的属性将由_Default解决。这些代码能够正常工作,但是这在理解上不如直接使用实际的属性。由于这些原因,应试着去避免在Visual Basic 6.0中使用无参缺省属性。而写为:
Dim obj As Object
Set obj = Me.Text1
MsgBox obj 'Relying on default property
MsgBox Me.Text1 'Relying on default property
直接使用:
Dim obj As Object
Set obj = Me.Text1
MsgBox obj.Text 'GOOD: Default property is resolved
MsgBox Me.Text1.Text 'GOOD: Default property is resolved
在Visual Basic.NET不支持无参缺省属性,然而却支持有参缺省属性。为了理解这两种类型的不同之处,认为有参数的缺省属性总是有一个索引。下面是ADO recordset 的缺省属性:Fields集的一个例子。代码:
Dim rs As ADODB.Recordset
rs("CompanyName") = "SomeCompany"
rs!CompanyName = "SomeCompany"
实际是如下代码的简单写法:
Dim rs As ADODB.Recordset
rs.Fields("CompanyName").Value = "SomeCompany"
rs.Fields!CompanyName.Value = "SomeCompany"
在这种情况下,Fields属性是有参数的,所以在Visual Basic.NET中,这种用法是有效的。然而,Fields的缺省属性是Value是无参的,所以在Visual Basic.NET要正确的用法是:
Dim rs As ADODB.Recordset
rs("CompanyName").Value = "SomeCompany"
rs!CompanyName.Value = "SomeCompany"
这个例子和大多数其它缺省属性在你的项目更新时就决定了,所以一个好的编程习惯就是在Visual Basic 6.0中解析进行。然而,你应该避免使用对象Object和变体Variant数据类型的缺省属性,因为他们在你的更新项目中不能被解析,而需要你亲自修改代码。
避免Null的传递
Visual Basic的早期版本支持Null传递。Null传递支持这个假设:当Null在某个表达式中使用了,而这个表达式的结果就是Null自己。在下面的例子中所有的结果V都是Null。
Dim V
V = 1 + Null
V = Null + Right$("SomeText", 1)
V = Right("SomeText", 0)
Null的传递在Visual Basic.NET中不能支持。在Visual Basic.NET中1+Null将产生一个类型不匹配的错误。另外,当Visual Basic 6.0具有两个版本的 Left函数--Left$返回一个字符串,Left返回一个变体,它可能是Null--而在Visual Basic.NET仅有一个版本Left,它总是返回一个字符串。
为了在Visual Basic 6.0 和 Visual Basic.NET中兼容,你应该总是协代码测试Null而不是依赖Null的传递。
Null传递在数据库应用程序中常常使用的,这时你需要测试数据库的字段是否包含Null。在这种情况下,你应该用函数IsNull()来测试结果并执行适当的操作。
涉及到一个相关的问题是用Null连接一个字符串。当对数据库对象编程时,将一个空字串连接到字段上来保证Null的值强迫为空字符串,这种操作是很常见的。例如:
MyString = rs!Field1 & ""
这种技术在Visual Basic.NET中也是支持的,当一个Null值与一个空字符串连接(使用&操作符),结果是空字符串。
使用0边界数组
Visual Basic 6.0允许你将数组的上下边界定义为任意整数。你也能够用ReDim来重新分配变体作为一个数组。为了保证与其他语言的交互操作,在Visual Basic.NET的数组必须具有0边界,除非变量先前已经被声明为数组,否则不能被ReDim为数组。尽管这样限制了数组的定义,但还是允许你在Visual Basic.NET 和任何其它 .NET 语言间传递数组。以下例子说明了这种限制:
Dim a(1 To 10) As Integer 'LBound must be 0 in VB.NET
Dim v
ReDim v(10) 'Can't use ReDim without Dim in VB.NET
Dim b(10) As Integer 'GOOD: Creates an array of 10 integers
ReDim b(5) As Integer 'GOOD: Can ReDim previously Dimed var
一个负面影响是0/1基址选择的好处没有了。
当你的项目更新到Visual Basic.NET时,任何基准选择都从你的代码中取消了。如果数组是0边界的,就不会改变,如果是非0边界的,就取消下边界并在代码中插入警告,如下面例子:
Dim a(1 To 10) As Integer
变为:
'UPGRADE_WARNING: Lower Bound of array a was changed from 1 to 0
Dim a(10) As Integer
在许多情况下,更新后的代码会象以前一样运行。然而,如果你的应用程序逻辑依赖于下边界1,那么你就需要做一些修改。Dim, ReDim, 和 Lbound描述将用警告被标记出来,以帮助你检查代码的改变。
由于这个原因,你应该在Visual Basic 6.0代码中使用0边界的数组,避免使用ReDim来实现数组的声明,也要避免使用下标为1的数组。
使用常量代替潜在的值
当编写代码时,试着使用常量而不是依赖于他们潜在的值。例如,如果你在运行时最大化一个窗体,使用:
Me.WindowState = vbMaximized 'Good: Constant name used
而不是:
Me.WindowStyle = 2 'Avoid using underlying value
Me.WindowStyle = X 'Avoid using variables
同样使用True 和False 来代替-1和0。
在Visual Basic.NET中一些值和某些情况下属性的名称和常数已经改变了。当你的项目更新到Visual Basic.NET中时,大多数常量已经为你自动改变了;然而,如果你使用了潜在的值和变量代替常量名时,大多数情况下,不能自动更新。使用常量将使你修改最少化。
在用户定义的类型中的数组和定长字符串
为了使得Visual Basic.NET中的数组和结构与Visual Studio.NET的其它语言完全兼容,定长字符串在Visual Basic.NET中不再支持了。在大多数情况下,着并不是什么问题,因为有一个兼容的类提供了定长字符串的行为,代码如下:
Dim MyFixedLengthString As String * 100
更新为如下:
Dim MyFixedLengthString As New VB6.FixedLengthString(100)
然而,定长字符串在结构(就是所谓的用户定义类型)中使用时是会引起问题的。问题的引起是因为定长字符串类在用户定义类型创建时没有自动的创建。另外一个问题是在用户定义类型创建时,固定大小的数组也没有创建。
当你的代码更新时,带有定长字符串或数组用户定义类型将会用注释标记出来,以告诉你在使用这个用户定义类型之前初始化定长字符串或数组。然而,你可以通过在Visual Basic 6.0中用字符串代替定长字符串和没有初始化的数组来代替固定大小的数组的方法来免于在Visual Basic .NET中修改代码。例如:
Private Type MyType
MyArray(5) As Integer
MyFixedString As String * 100
End Type
Sub Bar()
Dim MyVariable As MyType
End Sub
可更改为:
Private Type MyType
MyArray() As Integer
MyFixedString As String
End Type
Sub Bar()
Dim MyVariable As MyType
ReDim MyVariable.MyArray(5) As Integer
MyVariable.MyFixedString = String$(100, " ")
End Sub
避免继承特性
由于他们从这个语言中删除了,你因该避免使用这些关键字:
Def
Computed GoTo/GoSub
GoSub/Return
Option Base 0|1
VarPtr, ObjPtr, StrPtr
LSet
下面将更详细的作出解释。
Def
在Visual Basic的早期版本中,DefBool, DefByte, DefInt, DefLng, DefCur, DefSng, DefDbl, DefDec, DefDate, DefStr, DefObj 和DefVar在模块的声明部分中用来将变量定义为某种类型。例如:
DefInt A-C
定义所有的以A,B,C字母开头的变量为整型。而不用Def描述,你应该明确声明变量。
Computed GoTo/GoSub
Computed GoTo/GoSub描述使用如下形式:
On x GoTo 100, 200, 300
这在Visual Basic.NET中是不支持的。相反,你应该用If描述和Select Case结构。
GoSub/Return
GoSub 和 Return在Visual Basic.NET中是不支持的。在大多数情况下你能用函数和过程来代替它们。
Option Base 0|1
0|1基值的选择
0|1基值的选择在指定数组的下界时用到。正如前面所述,由于Visual Basic.NET只支持0边界的数组,这种描述在这个语言中已经取消了。非0边界的数组通过包装(原文:wrapper)类来实现。
VarPtr, ObjPtr, StrPtr
VarPtr, VarPrtArray, VarPtrStringArray, ObjPtr 和 StrPtr是用于得到变量内存地址的非文挡化的函数。这些函数在Visual Basic.NET是不支持的。
LSet
在Visual Basic 6.0中,Lset 描述可以被用来将一个用户定义的类型的一个变量分配给另一个用户定义类型的变量。这个功能在Visual Basic.NET中也是不支持的。
Windows APIs
许多API函数可以正确的在Visual Basic.NET中使用,就象在Visual Basic 6.0中一样,并警告你必须适当调整数据类型。在Visual Basic 6.0中的Long数据类型在Visual Basic.NET中是Integer类型,而Visual Basic 6.0中的Integer数据类型在Visual Basic.NET中是Short类型。在更新过程中,会为你完成这些转化,简单的API 就象在Visual Basic 6.0中运行的一样准确。例如:
Private Declare Function GetVersion Lib "kernel32" () As Long
Function GetVer()
Dim Ver As Long
Ver = GetVersion()
MsgBox ("System Version is " & Ver)
End Function
转变为:
Private Declare Function GetVersion Lib "kernel32" () As Integer
Function GetVer()
Dim Ver As Integer
Ver = GetVersion()
MsgBox("System Version is " & Ver)
End Function
另外在数字型的数据类型的更新中,Visual Basic 6.0有一个定长字符串的数据类型,在Visual Basic.NET是不支持的,它可以被更新为定长字符串包装类。在Visual Basic 6.0中大多数情况下你可以使用普通字符串来实现相同的功能。例如:
Private Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, ByRef nSize As Long) As Long
Function GetUser()
Dim Ret As Long
Dim UserName As String
Dim Buffer As String * 25
Ret = GetUserName(Buffer, 25)
UserName = Left$(Buffer, InStr(Buffer, Chr(0)) - 1)
MsgBox (UserName)
End Function
使用明确设置长度为25的普通字符串将更起作用,而不是固定长度的字符串:
Dim Buffer As String
Buffer = String$(25, " ")
在Visual Basic.NET中按如下更新:
Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
Function GetUser()
Dim Ret As Integer
Dim UserName As String
Dim Buffer As String
Buffer = New String(CChar(" "), 25)
Ret = GetUserName(Buffer, 25)
UserName = Left(Buffer, InStr(Buffer, Chr(0)) - 1)
MsgBox(UserName)
End Function
在某些情况下,Visual Basic.NET更好的处理了字符串到API函数的传递,因为使用ANSI 和 UNICODE 关键字你可以有选择的声明你将如何传递字符串。
有三种情况你可能需要做一些修改。第一种是传递带有固定长度字符串和字节数组的用户自定义的数据类型给API函数。在Visual Basic.NET中你或许需要改变代码,将MarshallAs属性(来自System.Runtime.InteropServices)增加到用户自定义类型的定长字符串或数组上。第二种情况是在Declare描述中使用As Any 变量类型。这在Visual Basic.NET中也是不支持的。变量的类型As Any通常使应在传递一个可能是字符串也可能是Null的情况下。在Visual Basic 6.0你可以通过使用声明两个API函数的方法来代替它,一个是长整型参数的,一个是字符型参数的。例如GetPrivateProfileString 这个API函数有一个As Any类型的参数lpKeyName:
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias
"GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal
lpKeyName As Any, ByVal lpDefault As String, ByVal
lpReturnedString As String, ByVal nSize As Long, ByVal
lpFileName As String) As Long
你可以通过声明两个版本的函数来代替"As Any",一个用来接收长整型,一个用来接收字符串:
Private Declare Function GetPrivateProfileStringKey Lib "kernel32" Alias
"GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal
lpKeyName As String, ByVal lpDefault As String, ByVal
lpReturnedString As String, ByVal nSize As Long, ByVal
lpFileName As String) As Long
Private Declare Function GetPrivateProfileStringNullKey Lib "kernel32"
Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String,
ByVal lpKeyName As Long, ByVal lpDefault As String, ByVal
lpReturnedString As String, ByVal nSize As Long, ByVal
lpFileName As String) As Long
当你希望传递一个Null值给API函数时,你使用GetPrivateProfileStringNullKey 的版本。这样做意味着函数可以更新到Visual Basic.NET中了。
如果你正在使用APIs执行线程的创建、Windows划分,消息队列挂起等等,那么你需要修改最后一个部分。一些函数可能会在Visual Basic.NET产生运行时错误。它们中许多API函数在Visual Basic.NET或 .NET框架中有对等函数。你不得不仔细的分清楚它们。
对窗体和控件的考虑
Visual Basic.NET有一个新的窗体包--Windows 窗体。Windows 窗体大致与Visual Basic 6中的窗体是兼容的。然而,如下列出了它们之间一些关键的不同之处:
Windows 窗体不支持OLE容器控件;你应该在Visual Basic 6.0应用程序中尽量不用这个控件。
在Windows窗体中没有shape控件。正方形和矩形就被更新为标签控件,而圆和椭圆是无法更新的。在你的应用程序中尽量不用这种形状。
在Windows窗体中没有斜线控件。水平和垂直的线被更新为label标签。线不能更新,你应该避免使用它。
Windows窗体有一套新的图形命令代替了窗体的方法Circle, CLS, PSet, Line, 和 Point。因为新的对象模块与Visual Basic 6.0中的有很大的 不同,所以这些方法不能更新。
对于时钟控件来说,设置Interval间隔属性为0来使时钟失效,而通过设定Interval为1来复位时钟。在你的Visual Basic 6.0项目中,设置Enabled 为 False 而不是设置Interval 为 0。
Windows窗体有两个菜单控件。MainMenu主菜单和 ContextMenu上下文菜单,在Visual Basic 6.0中只有一个菜单控件Menu,它既可以作为主菜单打开也可以作为上下文菜单打开。菜单控件可以更新到主菜单,但你不能把他们作为上下文菜单;你将必须重新创建上下文菜单。
Windows窗体不支持动态数据交换(DDE).
Windows窗体不支持Form.PrintForm方法。
尽管Windows窗体支持拖拉功能,但对象模型与Visual Basic 6.0有很大的不同。所以Visual Basic 6.0的拖拉属性和方法不能更新。
.NET框架结构有一个改进的粘贴板对象(System.Windows.Clipboard),它提供了比Visual Basic 6.0粘贴板对象更多功能,更多粘贴格式。然而由于这两种模块的不同,粘贴板的描述是不能更新的。
为了保证你的窗体更新到一个合适的尺寸,你总是在你的应用程序中应该使用缺省的twips的ScaleMode模式。在更新过程中,Visual Basic.NET把你的窗体坐标由twips转化为相匹配的象素。
Windows窗体只支持true-type和open-type字体。如果你的应用程序使用了其它字体,这些字体将被转化为系统缺省字体,所有的格式(大小、黑体、斜体和下划线)都将丢失。这将使用VB6的缺省字体MS Sans Serif。由于这个原因,不论在什么地方格式化文本时,我们推荐你使用Arial字体而不是MS Sans Serif字体。