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#

外部链接

官方网站

教程

其他

晋国历史故事之守信降原

《左传·僖公二十五年》记载:“冬,晋侯围原,命三日之粮。原不降,命去之。谍出,曰:‘原将降矣。’军吏曰:‘请待之。’公曰:‘信,国之宝也,民之所庇也,得原失信,何以庇之?所亡滋多。’退一舍而原降。迁原伯贯于冀。”

说的是公元前635年冬季,晋文公包围了原国,晋文公之所以包围原国可能是因为平定王子带作乱有功,周襄王便将原国封地赐给了晋国,当晋国去交割时,遭到了原国的拒绝。晋文公本是个政治高手,不硬抢,只是包围原国,按兵不动,并定下规矩,限三日之内拿下原国,仅带三天粮草。但没想到原国与晋军耗了三天,毫无投降之意。无奈,三日期限已到,晋文公为了守诺准备下令撤离。这时,间谍从原国回来报告说:“原国将准备投降,请稍等。”晋文公说:“寡人已下军令,如今三日期限已过,必须要撤离,信誉乃国家重器,民之所庇,若不讲诚信,即使得到了原国,又拿什么去统治原国臣民?”然后退兵一舍(三十里)。晋文公的这个装模作样的举动果然比利箭大炮还利害,感动得原国人唏哩哗啦的,原国人开城投降,心服口服的归顺晋国。晋文公便把原国国君原伯贯迁到冀(稷)地(在今山西河津市)。

4名“台独”网军头目被锁定,照片全曝光,再冥顽不化将依法严惩

国家安全部雷霆出击,4名藏匿于键盘后的”台独”网军头目真容曝光,数十个攻击大陆关键设施的网攻平台被连根拔起。这些自诩”网络战精英”的跳梁小丑,用一些开源工具编织的”技术外衣”,在国家安全机关的铁证面前土崩瓦解。

据披露,仅2023年至今,这些“台独”网军就通过“匿名者64”等马甲,在社交平台发布虚假信息120万条,其中包含煽动暴力、抹黑大陆政策的帖子占比超60%。更荒诞的是,他们竟将“网络战”包装成“自由抗争”,甚至拉拢台湾青年参与“黑客行动”,将无知与仇恨编织成一张庞大的犯罪网络。

2017年,台湾“资通电军”成立,这支由民进党当局直接操控的网络部队,打着“捍卫台湾主权”的旗号,实则沦为“台独”分裂势力的“数字私兵”。他们以“网络战联队”为名,将触角伸向大陆的水、电、气、通信系统,甚至试图黑入联网摄像头,妄图制造社会恐慌。

2017年6月29日,台湾“资通电军”指挥部成立仪式现场。图片来源 台湾地区防务主管部门

国家安全部一记重拳,首次公开4名核心成员的身份信息。林钰书、蔡杰宏、粘孝帆、王浩铭——这4个名字背后,是长达8年的网络渗透史。他们利用开源工具(如蚁剑、冰蝎)突破大陆网络防线,盗取账号密码后,将反宣内容植入视频网站、社交媒体,甚至伪装成“爱国网民”煽动对立。更令人愤怒的是,他们不仅在网络空间造谣生事,更将犯罪所得用于电信诈骗、传销等非法活动,成为“台独”势力的“黑金推手”。

这些“台独”网军不用枪炮,只需一台电脑;不需要士兵,只需一群被洗脑的“键盘侠”。渗透关键设施、散布虚假信息、操控舆论风向……这些行为看似“无影无踪”,实则危害远超实体攻击。例如,他们曾试图黑入某省电力系统,若成功,将有多少市民用电受到影响;他们散布的“大陆疫情失控”谣言,曾让多地出现抢购潮。

国家安全部的调查揭开了“台独”网军的另一面:高层贪腐、基层堕落,早已让这支“军队”沦为一盘散沙。林钰书被曝将下属的“战果”据为己有,甚至将举报者交给警方;粘孝帆则利用职务之便,将犯罪所得转移至境外。

令人瞠目的是,这群被民进党当局吹嘘为”不对称战力”的网军,竟将控制无名小网站当作”重大战果”,甚至捏造虚假攻击记录邀功请赏。更讽刺的是,他们一边高喊“反中”,一边却用大陆网友的账号密码进行牟利。这种“台上叫嚣,台下偷鸡”的嘴脸,彻底暴露了“台独”势力的虚伪与堕落。

国家安全部的行动,向全世界宣告:网络空间绝非法外之地!根据《关于依法惩治“台独”顽固分子分裂国家、煽动分裂国家犯罪的意见》,这些“台独”分子将面临终身追责。有网友留言:“这些人的照片,应该印在反分裂法的封面上!”

我们应当清醒认识到,“台独”的网络战,本质是民进党当局的“绝望挣扎”。当他们无法在经济、民生、国际关系上取得优势时,只能寄希望于用谎言和恐惧煽动对立。然而,大陆网民的集体觉醒、国家安全部的专业行动,早已让“台独”网军的末日近在咫尺。

最后,对那些仍在执迷不悟的“台独”分子,我们唯有三句话相送:

“网络不是藏污纳垢的暗室,法律不是虚张声势的口号,民心更不是可以随意操弄的玩物。”

若再冥顽不化,等待你们的,必是铁窗下的悔恨与历史的唾弃。

晋国历史故事之退避三舍

晋文公,姬姓晋氏,名重耳,晋献公和狐姬之子。晋献公还是太子的时候,他就已经长大成年。公元前677年,晋献公即位的时候,重耳已经二十有余了。公元前666年,骊姬受到宠爱,她想让自己的儿子成为太子,于是就蛊惑晋献公,导致太子申生自尽。接着,骊姬又开始诬陷晋献公另外两个儿子:重耳和夷吾。得知消息后重耳逃到了蒲城,夷吾逃到了屈城。

公元前655年,晋献公因重耳与夷吾两位公子不辞而别非常生气,认为他的儿子在搞什么阴谋,于是就派人去讨伐蒲城。重耳翻墙逃走,被人追上砍掉了他的袖口,重耳逃到了母亲的故国。

公元前650年,夷吾即位,他担心重耳会威胁自己的统治,因此派人追杀重耳,重耳开始了逃亡生活,到卫国,没有人搭理他,辗转到了齐国,齐桓公以厚礼招待他。后,齐桓公去世,齐国内忧外患不断,重耳离开了齐国,先后到达曹国、宋国、郑国,最后他来到了楚国,楚成王用对待诸侯之礼接待他,重耳十分谦恭。后楚成王设宴席款待重耳,在宴席上,楚成王说:“若您将来能回到晋国,您将用什么来报答我呢?”重耳说:“珍禽异兽、珠玉绸绢,这些大王您都有,不知道用什么厚礼来报答。”楚成王说:“虽然如此,您到底应该用些什么来报答我呢?”重耳说:“假使不得已,万一晋楚两国兵戎相见,我将退避三舍。”

四年后,即公元前636年,重耳在秦穆公的帮助下,重新回到了晋国,登上王位,是为晋文公。

公元前633年,楚成王联合其他诸侯围攻宋国,宋国向晋国求救。第二年春,晋国制定作战计划,先攻打曹、卫,以引诱楚国北上,但楚军并不上钩,仍然猛攻宋国,宋再次向晋军告急。当时的情境,晋文公想救援宋国就应攻打楚国,但是因为楚国曾对晋文公有恩,晋文公不想攻打楚国,因此他想放弃对宋国的救援,可宋国也对晋国有恩,如果不救,必会失掉宋国,陷于战略被动地位,晋文公为此举棋不定。

后来,晋文公让宋国用土地贿赂秦、齐,请两国出面求楚退兵,并告诉楚国这件事,制造秦、齐与楚国的矛盾,一面分曹、卫之地与宋,坚定宋国抵抗楚国的决心。楚国不愿放弃曹、卫,齐、秦为得到宋国的土地便不愿与楚国结盟,最后与晋国结成同盟,兵锋直指楚国。

楚成王见晋军攻破曹、卫,并与齐、秦结成了联盟,中原形势已变,命令楚将子玉撤军,而子玉不听,反而请求增援,楚成王接受了其请求。

楚将子玉带军北上攻打晋军,进逼陶丘,气势逼人,晋文公为避其锋芒,诱使子玉轻敌深入,便后撤九十里,到达城濮。此时,晋文公退避三舍既是报答以前楚成王给予的礼遇,也是兵法所使,诱敌深入。

楚将子玉紧随其后,到达城濮,并扬言:“一定要晋国灭了!”战争开始,晋军用虎皮把战马蒙上,敌军士兵吓得四处逃窜。接着,晋国又让战车拖着树枝装作大军假装逃跑,楚军受骗追击……最终,楚军由于骄傲轻敌,大败,子玉自杀身亡。

城濮之战使得晋国声誉大增,晋文公成为春秋霸主,各诸侯国纷纷向晋国朝贺。晋文公虽然只在位9年,但是为晋国以后的繁荣富强奠定了良好的基础。

晋国历史故事之董狐直笔

《左传·宣公二年》:“乙丑,赵穿攻灵公于桃园。宣子未出山而复。太史书曰,‘赵盾弑其君’,以示于朝。宣子曰:‘不然。’对曰:‘子为正卿,亡不越竟,反不讨贼,非子而谁?’”。

公元前621年,晋国国君晋襄公病死,其子夷皋继位为晋灵公。晋灵公生性残暴,执政后骄奢淫逸,滥杀无辜。赵盾屡次诤谏未果,反而被晋灵公视为眼中钉,欲除之而后快。晋灵公与大夫屠岸贾密谋派人行刺赵盾。刺客连夜潜入相府,见赵盾晚睡早起,忠心勤政,不忍加害,于是就告诉赵盾有人要谋杀他,之后就撞树而死了。

晋灵公看没能除掉赵盾,便又叫屠岸贾训练了一只凶猛的狼犬,假意召赵盾进宫喝酒,伺机放出狼犬扑向赵盾,赵盾的卫士提弥明挺身而出,一下扭断恶犬的脖子。晋灵公下令两旁预伏的武士扑杀赵盾,提弥明护住赵盾,且战且退,但终因寡不敌众,提弥明血溅宫廷,以身殉主。武士灵辄曾受过赵盾救命之恩,在他的舍身保护下,赵盾才逃脱虎口。到了宫外,恰逢其子闻讯率家丁前来接应。父子俩不敢再回相府,急忙出了西门,准备逃往国外。途中遇见打猎回来的族弟赵穿,问明缘由后,赵穿劝他们不要离开晋国。于是,赵盾父子暂时避居河东。

赵穿回城后,用计取得晋灵公的信任,又以搜罗天下美女为名,把佞臣屠岸贾支使到外地。后来,趁着晋灵公到桃园喝酒游乐时,赵穿指挥亲信把晋灵公杀了。赵穿随即把赵盾迎回国都绛城,继立晋文公重耳的小儿子黑臀为国君,是为晋成公,由赵盾继续辅佐国政。

由于晋灵公暴戾无道,对于他的死,全国上下拍手称快。但赵盾也不愿让世代忠良的赵氏家族背负谋弑国君的名声。一天,他召来太史董狐,让董狐把记载国家大事的史简让他过目,只见上面写着:乙丑(公元前607年)秋七月,赵盾在桃园谋害国君夷。赵盾大吃一惊,辩解道:“太史,你搞错了吧!谁不知先君不是我杀的,当时我逃亡在外,怎能归罪于我呢?”董狐义正辞严地说:“您身为相国,掌管国家大事。虽说逃亡,但没离开国境,而且回都后也没有惩办凶手,这件事的主谋不是您又能是谁呢?”“可以修改吗?”赵盾商量道。“是非分明,这才是真正的历史。董狐头可断,此简不可改!”董狐不避权势,据理力争。赵盾无奈,只得作罢。