晋国历史故事之困兽犹斗/鞭长莫及

公元前597年在邲之战中晋大败于楚,主帅荀林父请死。晋景公即将批准前,大臣士贞子劝道:“三十多年前,晋文公在城濮战了胜楚国,文公说楚军的主帅子玉还在,困兽犹斗啊!更何况子玉是一国的宰相呢?后来楚王杀了子玉,文公才放下心来。楚王杀子玉,是帮了晋国的忙。现在准许了他,结果会是怎么样?”景公恍然大悟,荀林父也官复原位。以后人们多用“困兽犹斗”比喻身处绝境仍然拼命抵抗的人。

但这时的晋景公作为霸主对中原各路诸侯已经感到“鞭长莫及”了,公元前595年楚国将晋国的同盟国宋国都城团团围住,双方相持了好几个月。第二年春天,宋国派大夫乐婴向当时的霸主晋国请求帮助。当晋景公准备出兵救援时,大夫伯宗劝道:“虽然我们鞭子长,也不能达到马致命的肚子上,我们又怎么能管得了南方的楚国呢?”于是景公就只派了一位叫解扬的大夫,到宋国去安慰了一番,并没有给宋国任何实际的援助。以后人们常用“鞭长莫及”来形容有心无力之人之事。

晋国历史故事之竭泽而渔/表里山河

晋文公回国后的第二年,周王室内乱,周襄王被迫离开都城,这时的晋文公不顾晋国百废待兴毅然送襄王回到周,并杀掉作乱者太叔带,又一次勤王成功,提高了晋国的国际地位。

公元前632年晋国为了救遭楚国侵略的宋国,发兵攻打楚的同盟国曹、卫,楚将子玉派使者以从宋撤兵为条件,要求晋国也不要再难为曹、卫。晋国暗许曹、卫来离间两国与楚的关系,并扣押使者,以此激怒子玉撤出宋国与晋交战。

晋军以战车七百辆,联合宋、齐、秦,与楚军对峙在今山东堙城西南的城濮,他问大臣狐偃如何战胜强大的楚军。狐偃献计用欺骗的办法。他又问另一位大臣雍季如何处理,雍季说用欺骗的办法只能是“竭泽而渔”,就是把池水抽干来捉鱼,到第二年就没鱼可捉了,打仗还是要靠实力。晋文公还是点放心不下,主将狐偃劝他:“打一仗吧!打胜了,我们就可以称霸诸侯;打不胜,晋国在表里山河之中,外有黄河,内有太行山、吕梁山,地势这样好,不用发愁。”

一句“表里山河”,到现在为止也是描写山西省地理形势最经典的词语。最后,晋文公用狐偃的计谋打败了楚军。马上就要打一场你死我活的激战之前,晋文公却信守当初许下的诺言,带领晋军后撤九十里。楚将子玉不知是计,结果穷追三次,导致兵将疲惫,晋军有备而来战胜了不可一世的楚军。但在论功行赏时雍季却在狐偃之上。他说:“我怎么可能以一时之利,来比百年大计的重要性呢?”接着召集诸侯举行盟会,自然晋文公当了霸主,并开启了一个半世纪的晋国霸业。

以后接受各路诸侯的朝见、进贡,他就把宾馆修的宽敞漂亮,客人就像回到家里一样,这在多年后郑国有名的大夫子产到晋国后,还念念不忘当年晋文公“宾至如归”的事。

晋国历史故事之秦晋之好

秦人先祖本为殷商嬴姓部族,周朝时在西北地区立国,始祖秦非子是商名将飞廉之后。前905年,秦非子因养马有功被周天子封为附庸国,号曰“秦嬴”。前821年,秦庄公击败西戎,被周宣王封为西陲大夫。前770年,秦襄公派兵护送周平王东迁,被封为诸侯,秦国正式成为周朝的诸侯国。经过百余年几代人的苦心经营,到秦穆公时,“益国十二,开地千里,遂霸西戎”,位列“春秋五霸”之一。

晋国则是周天子分封的姬姓小宗属国,首任君主唐叔虞为周武王姬发之子,周成王姬诵同母弟,母亲是齐太公吕尚之女、王后邑姜。晋国自晋献公时崛起,“并国十七,服国三十八”。鼎盛时,独霸中原,囊括今山西省全部、陕西省东部与北部、河北省中部与南部、河南省西部和北部、山东西北部与内蒙局部的广大地区。

秦国和晋国,一个是因功受封的后起之秀,一个是出身高贵的老牌诸侯,疆域比邻,又都有雄主相继出现,独霸西戎的秦国想图谋中原,必要突破晋国的阻碍,而晋国欲长期称霸中原,则须遏制秦国东进的势头。两国之间的战争曾经持续不断,自前627年至前558年,60多年间,秦晋经崤之战、彭衙之战、王官之战、新城之战、河曲之战、辅氏之战、麻隧之战、栎之役、迁延之役等重要战役,秦国被晋国牢牢封锁在函谷关和桃林塞以西,晋国控制了河西地区(秦晋大峡谷中下段的黄河西部区域)的诸多城池。

两个大国相爱相杀,拼命厮打的同时,也曾经有过骨肉相连的亲情岁月,那便是秦晋之好。出于政治考虑的联姻固然动机不纯,但血脉是不掺假的,大国博弈之下,兴许尚存那么一线温情,便被后世念念不忘。

前656年,即秦穆公四年、晋献公二十一年,秦国第九位国君嬴任好,迎娶晋国第十九任君主姬诡诸之女、晋太子申生的姐姐穆姬为妻。秦晋两国各自历史上非常有作为的雄主,成为了翁婿,从此血脉相融,纠葛不清。也是这一年,在晋献公宠爱的夫人骊姬诋毁陷害之下,太子申生被逼自尽,公子重耳、夷吾逃亡在外。前651年,晋献公去世。夷吾在姐夫秦穆公的帮助下回国继位做了国君,是为晋惠公,又在灾荒年得到秦穆公的援助,可他却屡屡背信弃义,导致在韩原战败被俘差点被杀,幸亏姐姐穆姬舍命求情,终得以回国,死后传位给儿子圉,是为晋怀公。而怀公生性刻薄,不能容人,晋国上下,人人自危。

此时,带着赵衰等人在外逃亡多年的晋公子重耳恰好辗转来到了秦国。对晋惠公、怀公父子二人都很失望的秦穆公,决定扶持重耳回国夺取政权,还把自己的女儿文嬴嫁与重耳为正妻,另外陪嫁了四个媵妾以示隆重,这其中便有秦穆公的另外一个女儿怀嬴。怀嬴本来是晋怀公子圉当年为偷跑回国继位而丢在秦国的前妻,论辈分算是重耳的前侄媳妇。想必这样的联姻,重耳并不是那么心甘情愿的,所以才有了《左传·僖公二十三年》里的这段描述:“秦伯纳女五人,怀嬴与焉。奉匜沃盥,既而挥之。怒曰:‘秦晋匹也,何以卑我?’公子惧,降服而囚。”后人据此提炼出秦晋之好、秦晋之匹、秦晋之缘等成语,以形容美好匹配的联姻。可对怀嬴的出现,重耳应该是不满的,以至于在怀嬴侍奉他盥洗时表现出不耐烦的情绪来,惹恼了这位秦国公主。

怀嬴一怒,重耳有点怕了,毕竟人家娘家是强大的秦国,何况自己的智囊赵衰给分析得很清楚:“《礼志》有之曰:‘将有请于人,必先有入焉,欲人之爱己也,必先爱人。欲人之从己也,必先从人,无德于人,而求用于人,罪也。’今将婚媾以从秦,受好以爱之,听从以德之,惧其未可也,又何疑焉?”现在正有求于秦国,联姻是合作的前提,怎么敢嫌弃怠慢人家的公主呢。于是,重耳赶紧找补,脱去上衣,像囚犯那样谢罪,随后又按周礼重新迎娶了怀嬴,以表达对秦国的尊重。

前636年,重耳在秦国军队的护送和赵衰等人的簇拥下,回到晋国都城曲沃,秦穆公派人杀死晋怀公,扶持重耳当上了国君,即为晋文公,晋国由此开启称霸天下的巅峰时代。

晋国历史故事之曲沃代翼

晋文侯的遗产

晋文侯(公元前805年——公元前746年),姬姓,名仇,晋穆侯之子,曲沃桓叔之兄,公元前780年——公元前746年在位,晋国第十一人国君。曾在周幽王之乱中护送太子宜臼东迁,建立东周,诛杀周携王,为东周初年局势稳定做出了很大的贡献。然而,为后来的“曲沃代翼”埋下了祸根。

公元前746年,晋文侯去世,太子伯继位,是为晋昭侯。晋昭侯不顾大臣师服的反对,将晋国重镇曲沃封给自己的叔叔成师,是为曲沃桓叔,师服:“建立国家应该本大而末小,即君主的力量、地盘应该大于臣下,才能够巩固统治地位。但是您却将曲沃封给成师,这就是破坏了等级的制度,肯定会危害其自身的统治地位”。因为曲沃的面积比当时晋国的翼城还要大,这显然是违反了当时的等级制度。

曲沃桓叔的野心

公元前739年,晋国大臣潘父刺杀了晋昭侯,准备迎纳曲沃桓叔。曲沃桓叔:“我在曲沃经营多年,深得民心如今时机已到,是时候夺取晋国国君之时了”。桓叔趁机发兵翼城,但是晋国国人起兵反抗,曲沃桓叔失败退回了曲沃。晋国人拥立晋昭侯之子公子平为国君,是为晋孝侯,并且诛杀了潘父等人。史称“曲沃代翼第一战”,曲沃战败,晋君获胜。

曲沃庄伯的挑衅

公元前731年,桓叔成师去世,其子庄伯继承其父之位。公元前724年,曲沃庄伯派人到晋国都城翼城弑杀了晋孝侯,晋国人在荀国等诸侯国的援助下击败了曲沃庄伯,晋人拥立晋孝侯之弟公子隰为君,是为晋鄂侯。史称“曲沃代翼第二战”,曲沃败,晋君胜。

诸侯援助的失败

曲沃庄伯失败,联合郑国、邢国,并贿赂周王室出兵助阵。当时的周天子周桓王派出了两位大夫领兵助阵,但是由于分账不均,周桓王转而支持晋鄂侯,派兵讨伐曲沃庄伯。曲沃庄伯再次失败退回到了封地,史称“曲沃代翼第三战”,曲沃战败,晋君胜。

曲沃武公的崛起

公元前716年,曲沃庄伯去世,其子武公继承其父之位。曲沃武公比起父、祖更加有手腕,利用外交手段,再次贿赂周王室和周边的诸侯国,逐渐壮大自己的力量。公元前709年,曲沃武公对晋国发动了进攻,掳走了晋哀侯。公元前706年,诱杀了小子侯。周桓王派兵维和,曲沃武公退回曲沃。

曲沃武公的胜利

公元前678年,经过67年的内战,曲沃武公终于攻占翼城,杀死了晋侯緡,灭了晋国大宗。为了防止周天子的干涉,曲沃武公将缴获的宝贝全部用来贿赂周天子,周天子封曲沃武公为晋国国君,位居诸侯之列,史称“晋武公”。从此,曲沃桓叔一脉切底打败了晋文侯一脉,成为了晋国的大宗。

Visual Basic .NET

概述

Visual Basic .NETVB.NET)是.NET Framework框架下的一种多重编程范式高级语言。

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定义的数据类型。

类型名字节长度取值范围表示法
Short2字节-32768~32767number S
Integer4字节-2 147 48 3 648~2 147 483 647number I
Long8字节-9223372036854775808 ~ 9223372036854775807number& numberL
Single4字节7位有效数字num! numberF
Double8字节15/16位有效数字id# numberR
Decimal16字节29位有效数字id@ numberD
Currency8字节小数点右4位,左15位number@
Byte1字节0-255
Char2字节UTF-16字符“d”C
DateTime8字节0001-01-01T00:00:00.000 ~ 9999-12-31T23.59.59.999#4/102008 06:01:23.456 PM#
Boolean2字节True(-1) False(0)
StringUBSTR, 字符数量*2+2UTF-16字符串“Hello”$
Object4字节
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 Boolean
Dim 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语句
If 条件 Then
    语句
ElseIf 条件 Then
    语句
Else
    语句
End If
  • Switch语句
Select Case Variable
     Case Value1
         Statements
     Case Value2
         Statements
     Case Value3
         Statements
     ...
     Case Else
         Statements
End Select

循环语句

包括下述几种:

  • For…Next循环
For varName = 初值 To 终值 [Step 步长]
    循环体语句
Next varName
  • Do循环
Do [{While|Until} condition]
   statements
   [Exit Do]
Loop

Do
  statements
  [Exit Do]
  statements
Loop [{While|Until} condition]
  • While循环
While condition
   statements
   [Exit While]
   statemenst
End While
  • For Each…Next循环
For Each element in group
    statements
Next [element]

Yield语句

实现迭代器遍历一个序列,每次获取一个返回值。迭代器可以作为一个方法或属性的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)

接口是一类特殊的抽象类,不能包括可运行代码与类的数据成员的声明:

    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

多态(Polymetric)

基于继承的多态,是指用基类类型的变量绑定不同的子类对象,这样调用基类变量的方法,在运行时动态确定实际运行了哪个派生类的同名的方法。多态的优点是可以针对基类(或接口)的方法来写一个通用的过程或者数据容器,适用于各种不同的派生类的具体实现。

委托(Delegate)

委托本质上是一种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语句,定义一个范围,在范围结束时自动释放对象所占用的资源。

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}

匿名函数或lambda表达式

即无名的函数或过程,作为表达式的值。可以写为一行或多行。例如:

Dim func1=Function(i As integer) i+10
Dim action = sub()
  End Sub
Dim func2 = Function()
  End Function

可以在声明匿名函数的同时调用它。单行的lambda表达式不能使用Return关键字,其返回类型是自动推导得出;其参数要么都是用As关键字指明类型,要么全部是自动推导出类型。

lambda表达式在定义时可以使用所在上下文(context,即C++语言的闭包closure)的局部变量、参数、属性、Me等等的值,即使lambda表达式离开了定义时所在的context,这些被使用的局部变量等的值仍然有效。这是因为lambda表达式在定义时把所用到的context的值保存到它自己的定义类中。lambda表达式可以嵌套定义。

扩展方法

例如:

Imports System.Runtime.CompilerServices
 Public Function funcName(ByVal ins As className) As String
    'Do something
End 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

LINQ

From element [ As type ] In collection [, element2 [ As type2 ] In collection2 [, ... ] ] [Where 表达式]

例子(Hello World)

这里给出了一个Hello World的例子。通过它们您可以更好地理解Visual Basic的特性。(此源代码运行于命令行下)

Module Mdl_Main
    Sub Main()
        Console.WriteLine("Hello World")
    End Sub
End Module

这个程序能输出 Hello World 

Module Mdl_Main

第一行是模块定义,命名空间的定义一般可以省略。VB.NET中,所有函数,过程与变量的声明都必须在模块或者类的内部,而不能直接存在于命名空间内部。

Sub Main()

第二行定义了名为Main的过程。一般来说,“Sub Main()”是程序的入口点。

Console.WriteLine("Hello World")

第三行输出“Hello World”。

End Sub

第四行结束了过程Main的定义。

End Module

第五行结束了模块Mdl_Main的定义。

与旧版VB比较

与旧版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) Handle 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#等C家族语言比较

与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#的很多不同之处:

  • Visual Basic:
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
  • C#:
namespace N
{
	//Comment
	static class M
	{
		int GetSum(int[] arr)
		{
			var Sum = 0;
			int i;
			
			foreach(i in arr)
			{
				Sum += i;
			}
			
			return i;
		}
	};
	
	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框架下方便地互相调用与协同开发。关于两者的优劣一直见仁见智。

历史

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-03-08微软拒绝为VB6再提供维护与支持的回应,当月月底出现了反对者的请愿。

VB.NET的支持者们认为新语言在很多方面比旧版本更为强大,比如它以相比早期版本更为自然、紧密和完全的方式地加入了现代面向对象的编程范式。反对者们有不同意见,虽然VB6对对象模型支持有缺点,但是二次开发升级到VB.NET的成本比升级后的收益要高得多。而开发软件发布因特网版本的独立程序员也对VB.NET的RunTime尺寸过大不满。

针对开发者的不满,微软主要做了如下努力:使新的开发更容易启动,而把已开发的VB6代码升级到VB.NET。例子主要包括:完成VB6中的常见任务如打印预览;集成VB6和VB.NET解决方案(dubbed VB Fusion),从VB6代码转换到VB.NET。

微软在后续版本中撤销了一些过激的更改,并且吸取了经验。在以后版本中,语法的更改变得更加谨慎。

2003年Visual Basic .NET 2003(VB 7.1)

Visual Basic .NET 2003(VB 7.1)和.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日发布。

参考数据

参见

Visual Basic Visual Studio C#

外部链接

官方网站

教程

其他