1、System.Object
每个变量、控件、窗体都继承了System.Object
2、对象的声明与实例化
简单说声明,只是说明类型,实例化说明在内存中分配了空间。
用New来创建对象,得到类的一个新实例
下面有5种实例化形式,其中3较为标准且可读化高。
Dim a As theClass '1,用两语句来创建实例,先声明再实例化 a = New theClass() Dim b As New theClass() '2,仅一个语句实例化 Dim c As theClass = New theClass() '3,仅用一个语句实例化,更能表明类型与创建,在接口/继承上更好用 doSomeThing(New theClass()) ' 4,参数中创建实例 doSomeThing(New theClass().getValue()) '5,参数中创建的同时调用其方法
3、对象引用
通常使用对象都是使用对象的引用。对象的引用(对象变量)本质上就是对象的指针就同C++的指针一样。
当用New创建一个对象时,就会将对象的引用(指针)存储到一个变量中。
下面是对象a,和b赋值时本质情况,在C++中被称为浅复制
4、取消对象
给一个对象引用赋值为Nothing时,就取消了这个对象的引用。
经实验,Nothing实际上存储的是0,和C++一样给一个对象变量设置为0时,就取消它指向堆中分配的空间。
这时.Net会知道:这个对象不再需要,运行库会在某时刻销毁该对象,收回内存及资源。因此在.Net删除对象
之前,Framework会为该对象调用Finalize方法。
5、前期绑定与后期绑定
前期绑定:编译时就知道类型,故能准确地分配空间指定大小,运行速度快
后期绑定:编译时不知道,只有运行时才知道,它提供了灵活性(但IntelliSense也就失效了),由于是运行时动态
分配所以速度慢。
后期绑定容易出错,所以一般要配合Try....Catch...进行处理异常情况
(option Strict off就是可以后期绑定,默认)
6、类型转换
隐式转换与显式转换
Cint,Clong....等是为了兼容由VB6转向VB.net,这并不是最佳的方式。
VB.net提供了几个显式转换。
(1)Convert转换类
可用Convert.ToLong(变量)之类,把变量转换成Long型
此类只能将已经一些基本类型已经明确知道类型纳入到其中的函数,并不能代表全部。
注意:1、如果出现错误,将抛出异常。比如将负数转为非负的UInt32
2、共享方法MaxValue,MinValue勿需参数就可得到值如:Long.MaxValue
(2)Parse、TryParse方法
仅用于值类型,将字串转为相应的数值类型
result=Long.Parse("100")
如果失败,将抛出异常,而异常会消耗额外的系统资源,影响性能。
于是TryParse出场,它封装了异常处理,只返回是否成功的逻辑值,
成功,返回True,失败为False,常用于转换前判断。
dim a as Long
if Long.TryParse("100",Long) then
b=a
end if
(3)Ctype函数
默认Option Strict是关闭的,因此是可以隐式转换,但如果开启了,一些转换就不能进行,就可以用Ctype指定。
dim a as object=c
dim b as string
b=a '若启option strict将出错,这时须指定为Ctype(a,string)
CType若失败,将引发异常
(4)DirectCast( a,b)函数
把a转为b类型,仅用于引用类型且用于假定可以直接转换的,不能对转换数据执行额外的处理,即不具有主动性。
常用于具有继承关系的类型。失败将产生异常。
如果说CType是智能体,可以转换任意类型,那么DirectCast只能转换具用继承判断的引用型
(5)TryCast
TryCast与DirectCast类似,不同的时,因封装了异常处理,它不会抛出异常。
如果成功,返回正确转换后的类型;
如果失败,返回Nothing
TryCast用于继承等的引用类型,不会抛出异常。
===========================================================================================
类
对象是由类产生,对象是类的一个实例。
1、创建类
用Class关键字来创建类
Pulbic Class Person
...................'Code
End Class
最常见的是每个文件只包含一个类。
注意:我们可以发现一个简单的窗体程序就只有一个类,而没有什么实例产生,或运行。
这是什么原因呢?
原来:首先启动窗体时候已经实例化了一个对象,该对象会有一个线程,通常我们称为UI始终监视信息泵系统,
如果接受到类似的拖动,点击,重绘信息,消息泵就会去通知UI,让UI来处理
2、字段
字段即C++的数据成员,是用来存储数据的。每产生一个对象都会产生一个字段的副本。
注意关键字的作用域 :
Private 私有,只能用于类中代码
Public 公有,类内类外的任何程序集的的任何项目都可使用
Protected 保护,只用于该类继承的类
Friend 友元,只能用于项目或组件的代码
Protected Friend 用于项目或组件的代码以及项目内或项目外从该类继承的类
Public Class People Private mName As String '字段,即数据成员 Private mBirthday As Date End Class
3、方法
方法是类的方法成员,由sub或function等来完成对数据成员的操作,或对外部的一处理。
sub 是不用返回值
function 需返回值,返回值在代码中用return来指明,或者用方法名(函数名)赋值取得
Public Function Age() As Int32 Return CInt(DateDiff(DateInterval.Year,mBirthday,Now())) '用return返回值 End Function Public Function Age() As Int32 Age = CInt(DateDiff(DateInterval.Year,Now())) '用方法名取得返回值 End Function
4、方法的作用域
它与字段的作用域一样。比如:
Friend的方法,表明对于 项目内的代码这是对象接口的一部分,但使用该程序集的其它应用程序或项目不能调用。
5、方法的参数
参数与前面的sub,Function一样。
对于值传递用byval,或用引用传递使用ByRef,这样在方法中更改其值,可使原值发生变化。
Public Class People Private mName As String '字段,即数据成员 Private mBirthday As Date Private mTotalDistance As Int32 Public Sub Walk(ByVal distance As Int32) '若需改变外部distance值,这里可改byval为byref mTotalDistance += distance End Sub Public Function Age() As Int32 Return CInt(DateDiff(DateInterval.Year,Now())) '用return返回值 End Function End Class
6、属性
.net提供了一种特殊的方法,称属性,使用关键字Property。
本质上它还是方法,只是为了分类、理解更容易,结合前面的字段(数据成员),提供一种新的方法称属性。
比如前面的字段mName,如果设置成Public,原理上可以的,但和我们设计类的封闭性违背。
这种情况一般用一个方法来代码对字段的直接操作,而原字段设置成Private,就完善了对数据封装的概念。
由于常用这个的方法来操作较为频繁,于是设计成一个Property属性(方法)来代替,用Get实现读取字段,
用Set来实现给字段赋值。
这样有几个好处:
1、完善了类的封装;
2、实现了对字段值的过滤,比如赋值时,如果是负数(不允许为负时)可以在代码中提示。
3、细化了字段的读和写,有时只准读,有时只准写,这样分类进行限制。
4、对范围进行限制,有些只准在项目内使用,有些可以。(用Friend来限制)
例:下面是一个属性的定义
Public Property mName() As String Get Return mName End Get Set(value As String) mName = value End Set End Property
注意:1、属性名和字段名各不相关,可以相同,也可以不同(最好设置不同,例中为相同)
尽管属性中操作的是一个(或多个)字段,只有明白内部的代码才能知道对应的是哪个字段。
例中mName属性与字段mName并不相关,对生成的对象成员中显示的属性名。
2、对于一般不须限制的属性可以直接用下面简化成一句即可。
Public Property mName() As String
效果与 Public mName as String一样
“自动实现的属性”使您可以快速指定类的属性,而无需编写代码对该属性执行 Get 和 Set 操作。
通过自动实现的属性,可在一行中声明一个包含默认值的属性。
Public Property Name As String Public Property Owner As String = "DefaultName" Public Property Items As New List(Of String) From {"M","T","W"} Public Property ID As New Guid()在声明自动实现的属性时,Visual Basic 会自动创建一个隐藏的私有字段(称为“支持字段”)来包含该属性的值。
例如,如果声明一个名为 ID 的自动实现的属性,则支持字段的名称为 _ID。
如果有一个类成员的名称也是 _ID,则会产生命名冲突并且 Visual Basic 会报告编译器错误。
此外,支持字段还具有下列特性:
支持字段的访问修饰符始终为 Private,即使该属性本身具有不同的访问级别(如 Public)也是如此。
如果该属性标记为 Shared,则支持字段也是共享的。
为该属性指定的特性不应用于支持字段。
可从类中的代码以及从监视窗口等调试工具中访问支持字段。 但是,支持字段不会显示在 IntelliSense 文字完成列表中。
必须改用标准的“扩展”属性语法(此时不能用自动实现的属性功能)。
如果要执行下列任一操作,则必须使用扩展属性定义语法:
向属性的 Get 或 Set 过程添加代码,如用于验证 Set 过程中的传入值的代码。 例如,在设置属性值之前,您可能希望验证一个表示电话号码的字符串是否包含所需数目的数字。
为 Get 和 Set 过程指定不同的可访问性。 例如,您可能希望将 Set 过程设为 Private,将 Get 过程设为 Public。
创建 WriteOnly 或 ReadOnly 属性。
使用参数化属性(包括 Default 属性)。 若要为属性指定参数,或者为 Set 过程指定附加参数,必须声明扩展属性。
为支持字段设置特性,或者更改支持字段的访问级别。
为支持字段提供 XML 注释。
下例是限制赋值时,只能在项目内生效,项目外不能赋值。
Public Property mName() As String Get Return mName End Get Friend Set(value As String) '仅限于项目内使用 mName = value End Set End Property
7、参数化属性
这样,它可以为某些设置一个可选范围,或者成一个数组,如:电话号码可存储多值。
为此,我们可以把mPhone电话号码属性设置成哈希表类型。
例: 参数是“索引”
Private mPhones As New Hashtable '哈希表类(集合) Public Property Phone(ByVal location As String) As String '参数类似索引在哈希表中定位 Get Return mPhones.Item(location) End Get Set(value As String) If mPhones.ContainsKey(location) Then '判断是否已经有此索引 mPhones.Item(location) = value '有,直接更新值 Else mPhones.Add(location,value) '无,加入索引及值 End If End Set End Property
注:哈希表,本质上同数组相同,都是通过“索引”来取得或设置值。但数组是“数值”型的索引,而哈希表索引可以是其它类型
比如字符串,数组是连接存储,哈希表是通过“索引”(关键字)映射取得。
另外,哈希表比数组灵活,但更浪费空间。
正如前面所说,在Property前加入ReadOnly(只读)或WriteOnly(只写),就可限制对属性的操作。
如:
Public WriteOnly Property Amber() as int32
set(ByVal Value As integer) ‘只读,当然只有Set而没有Get
mAmber=Value
End Set
End Property
9、默认属性
对象可以实现默认属性,用它时,不用指明属性,会自动赋值或获取对应的某属性。
Private mPhones As New Hashtable Default Public Property Phone(ByVal location As String) As String '用default表示这个属性当作对象的默认值 Get Return mPhones.Item(location) End Get Set(value As String) If mPhones.ContainsKey(location) Then mPhones.Item(location) = value Else mPhones.Add(location,value) End If End Set End Property '================================================================================ Dim myPerson As New People myPerson.Phone("home")="12345678" '没有指定为默认属性时,必须这样明确指明属性 myPerson("home")="12345678" '一旦指明默认属性为phone时,可简化成此句,自动知道是Phone属性
猜想是不是不带参数时,VB.net无法判断是隐式的类型转换还是给默认属性进行赋值?对否?