信息发布软件,b2b软件,广告发布软件

 找回密码
 立即注册
搜索
查看: 3789|回复: 10
打印 上一主题 下一主题

[『VB.NET 图文教程』] 在VB.NET编程中使用数组让您编程有一个质的速度

[复制链接]

1845

主题

1855

帖子

1万

积分

积分
10788
跳转到指定楼层
宣传软件楼主
发表于 2017-5-16 13:10:26 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

软件教程首图:

软件教程分类:VB.NET 图文教程 

软件图文教程视频教程分类:软件图文教程 

软件教程难易程度:软件高级教程 

软件教程发布日期:2017-05-16

软件教程关键字:在VB.NET数组

① 本信息收集于网络,如有不对的地方欢迎联系我纠正!
② 本信息免费收录,不存在价格的问题!
③ 如果您的网站也想这样出现在这里,请您加好友情链接,我当天会审核通过!

④友情链接关键字:软件定制网站 网址:http://www.postbbs.com

软件教程详细描述
本帖最后由 群发软件 于 2017-5-16 13:13 编辑

 数组是程序中经常要使用到的一种数据类型,Visual Basic.Net中的数组,虽然语法结构等方面保留了和Visual Basic的很多相似之处,但也与Visual Basic存在着很多区别。其最大,也是各位Visual Basic程序员所最不能容忍的区别就是如下二点:

  1. 在Visual Basic .Net中申明一个数组,其数组元素中的索引值的起点全部都为“0”,而不是以前Visual Basic中的索引值起点一般都为“1”。这种定义方法和Visual Basic .Net的孪生姐妹Visual C#非常相似。

  2. 由于在Visual Basic .Net中数组都有了统一的起点,所以在Visual Basic .Net中定义一个数组,也就不再需要关键字“To”来设定数组的范围。这样在Visual Basic .Net中申明一个数组将会比Visual Basic中要稍微简洁一点。关于数组定义将在后面详细介绍。

  一.本节主要内容:

  在接下来内容中,将结合具体示例来详细的介绍下列知识点:

  1. 申明数组,其中包括一维数组、多维数组,也包括静态数组和动态数组,及其初始化。和访问数组中的元素。

  2. 重新申明数组,即ReDim语句的使用用法,及其Preserve关键字的作用。

  3. 使用For Each …. Next语句来遍历数组中各个元素,For Each …. Next语句是操作数据最为常用的一种语句,它能够方便的访问到数组中的每一个元素。

  4. 申明参数为数组的过程或者函数,由于数组是引用类型,所以在申明参数为数组的函数或过程时,处理方法与参数为值类型的函数或过程有点不一样。

  5. 简要介绍Array类和其主要的常用,以及通过Array类操作数组的具体方法。

  在Visual Basic.Net申明一个数组使用的依然是Dim语句,其申明数组和Visual Basic的主要区别在上面内容中已经简单说过了。下面在Visual Basic .Net申明一个长度为“3”的字符串数组,并对之进行初始化的代码:

  Dim arrString ( 2 ) As String = {"星期一","星期二","星期三"}

  下面代码是申请一个2×2的二维字符串数组,并对之进行初始化:

  Dim arrDate ( 1, 1 ) As String = {{"星期一", "18号"}, {"星期二", "19号"}}

  静态数组和动态数组的区别就在于静态数组的长度是固定的,而动态数组的长度是不固定的。上面的申明的二个数组就是静态数组,而下面二段代码的作用就是分别申明一个一维数组和二维数组,并对它们进行初始化:

  Dim arrString ( ) As String = {"星期一","星期二","星期三"}

  '申明一个动态的一维数组,并初始化

  Dim arrDate ( , ) As String = {{"星期一", "18号"}, {"星期二", "19号"}}

  '申明一个动态的二维数组,并初始化

  对其他数据类型和更多维数的数组,其申明和初始化方法和上面的基本差不多,只需根据数组的维数和数据类型的不同进行相应的修改就可以了。

  当数组申明和初始化以后,就可以通过元素在数组中对应的索引值来访问,下面二段代码分别是访问上面申明并初始化的一维数组和二维数组中的一个元素:

  Dim sTemp1 As String = arrString ( 1 )

  '访问arrString数组中的第2个元素

  Dim sTemp2 As String = arrDate ( 1 , 1 )

  '访问arrDate数组中的第二行、第二列元素

  三.重新申明数组:

  在Visual Basic .Net重新申明数组和Visual Basic中基本类似,依然使用的是ReDim语句。在Visual Basic .Net中使用ReDim语句要注意以下三点:

  1. ReDim语句仅可以在过程级出现。这意味着不可以在类或模块级代码区使用ReDim语句来重新申明数组。

  2. ReDim语句只是更改已被正式声明的数组的一个或多个维度的大小,但不能更改该数组的维数。

  3. ReDim语句无法更改数组中元素的数据类型,和Dim语句申明数组的区别在于无法在ReDim语句中初始化重新申明的数组。

  在使用ReDim重新申明数组时,最为常见的关键字就是“Preserve”。“Preserve”的作用是表明在重新申明数组时,是否要在重新申明的数组中复制原数组中的元素。请比较下面二段代码:

  代码一:

  Dim arrString ( 2 ) As String = {"星期一","星期二","星期三"}

  ReDim Preserve arrString ( 4 )

  '重新申明arrString数组,数组的长度改为5,并且在新数组中复制原数组的元素

  arrString ( 3 ) = "星期四"

  arrString ( 4 ) = "星期五"

  代码二:

  Dim arrString ( 2 ) As String = {"星期一","星期二","星期三"}

  ReDim arrString ( 4 )

  '重新申明arrString数组,数组的长度改为5,并不往新数组中复制原数组的元素

  arrString ( 0 ) = "星期一"

  arrString ( 1 ) = "星期二"

  arrString ( 2 ) = "星期三"

  arrString ( 3 ) = "星期四"

  arrString ( 4 ) = "星期五"

  通过比较上述二段代码,可见,在第一段代码中由于ReDim中使用了Preserve关键字,所以在重新申明数组时,就在新数组中复制了原数组的元素,这样就只需要对其中的二个元素进行初始化;而第二段由于没有使用Preserve关键字,就没有在新数组中带入原数组中的任何元素,所以对数组的所有元素都进行初始化。通过比较相信您对重新定义数组和“Preserve”关键字的使用有了更深的理解。

  用Photoshop给漂亮的烫发MM抠图

  Photoshop透明婚纱抠图大法

  Photoshop:让MM做个“变色龙”

  用Photoshop来制作一款精美的宝宝照片墙

  Photoshop绝色美女通道抠图法

  用Photoshop教你打造绚丽光芒效果

  For Each …. Next语句好像只是为二种数据类型专门度身定做的,其一就是集合,另外一个就是数组了。通过For Each …. Next语句,可以十分方便的访问数组中的任一元素。请仔细分析一下下列代码:

  Dim arrString ( 2 ) As String = {"星期一","星期二","星期三"}

  Dim Temp As String

  For Each Temp In arrString

  If Temp = "星期三" Then

  MsgBox ( "在数组中寻找到""星期三""字符串")

  Exit For

  '退出For Each …. Next语句

  End If

  Next

  上面代码的功能是通过For Each …. Next语句访问arrString数组中各元素,如果发现有元素为字符串“星期三”,则弹出提示框,并退出循环。

  同样用For … Next语句也能够实现上面同样的功能,只是感觉有点不专业,并且有点繁琐,下面代码是用For … Next语句实现上面For Each …. Next语句同等功能的代码:

  Dim i As Integer

  For i = 0 To myString.Length - 1

  If arrString ( i ) = "星期三" Then

  MsgBox ( "在数组中寻找到""星期三""字符串" )

  Exit For

  End If

  Next

  五.申明参数为数组的过程或者函数:

  由于数组为引用类型,所以如果以数组为参数过程和函数在定义时候就要多加以注意,下面代码是在Visual Basic.Net申明一个参数为数组的过程的典型代码,可见在调用数组类型之前多了一个关键字“ByVal”,“ByVal”关键字的作用在于在下面调用的过程中的不能更改数组的数值:

  Sub DisplayArray ( ByVal myString ( ) As String )

  End Sub

  六.简要介绍System.Array类及其成员:

  Array类是一个基类,是公共语言运行库中所有数组的基类。它提供了创建、操作、搜索和排序数组的方法。数组中任一个元素就是Array中的一个值。Array的长度是它可包含的元素总数。Array的秩是Array中的维数。Array中维度的下限是Array 中该维度的起始索引,多维Array的各个维度可以有不同的界限。表01和表02分别是Array类的常用属性和常用方法及其说明:


属性 说明
IsFixedSize 获取指示Array是否具有固定大小的值。
IsReadOnly 获取指示Array是否为只读的值。
Length 获取Array的所有维度中的元素总数。
Rank 获取Array的秩(也就是维数)。

表01:System.Array类的常用属性及其说明


方法 说明
BinarySearch 使用二进制搜索算法在一维的排序Array中搜索值。
Clear 将Array中的一系列元素设置为零、false或空引用(即:Nothing),具体操作时设定值取决于元素类型。
Copy 将一个Array的一部分复制到另一个Array中,并根据需要执行强制类型转换和装箱。
CopyTo 将当前一维Array的所有元素复制到指定的一维Array中(从指定的目标Array索引开始)。
GetLength 获取Array的指定维度中的元素数。
GetLowerBound 获取Array中指定维度的下限。
GetUpperBound 获取Array的指定维度的上限。
GetValue 获取当前Array中指定元素的值。
LastIndexOf 返回一维Array或部分Array中某个值的最后一个匹配项的索引。
Reverse 反转一维Array或部分Array中元素的顺序。
SetValue 将当前Array中的指定元素设置为指定值。
Sort 对一维Array对象中的元素进行排序。


  表02:System.Array类的常用方法及其说明

  下面介绍的示例的功能包含了数组的申明、初始化、重新申明、重新初始化、数组中各元素的排序、数组的遍历、查找以及以数组为参数的过程的定义及调用方法等。下面是此示例实现的具体步骤:

  1. 启动Visual Studio .Net。

  2. 选择菜单【文件】|【新建】|【项目】后,弹出【新建项目】对话框。

  3. 将【项目类型】设置为【Visual Basic项目】。

  4. 将【模板】设置为【Windows应用程序】。

  5. 在【名称】文本框中输入【数组】。

  6. 在【位置】的文本框中输入【E:VS.NET项目】,然后单击【确定】按钮,这样在“E:VS.NET项目”目录中就产生了名称为“数组”的文件夹,并在里面创建了名称为【数组】的项目文件。

  7. 把Visual Studio .Net的当前窗口切换到【Form1.vb(设计)】窗口,并从【工具箱】中的【Windows窗体组件】选项卡中往Form1窗体中拖入下列组件,并执行相应操作:

  四个Button组件,分别用来创建一个“创建一维数组”、创建“创建二维数组”、实现对“对一维数组排序”和实现“重定义一维数组”。并在这四个Button组件拖入Form1的设计窗体后,分别双击这四个组件,这样系统会在Form1.vb文件分别产生这四个组件的Click时间对应的处理代码。

  一个ListBox组件,用来显示创建的一维数组的内容。

  8. 按照表03中数值来设定设定组件的主要属性:


组件类型 组件名称 属性 设置结果
Form Form1 Text 数组篇
Form1 MaximizeBox False
Form1 MinimizeBox False
Form1 FormBorderStyle FixedSingle
ListBox ListBox1 ItemHeight 12
ListBox1 Location Point ( 28 , 169 )
ListBox1 Size Size ( 246 , 136 )
Button Button1 Text 创建一维数组
Button1 FlatStyle Flat
Button2 Text 创建二维数组
Button2 FlatStyle Flat
Button3 Text 对一维数组排序
Button3 FlatStyle Flat
Button4 Text 重定义一维数组
Button4 FlatStyle Flat


  【数组】项目窗体中各组件的主要属性设定数值表



  并按照图01中各组件的位置、大小和排列方式来调整窗体中各个组件:

在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件

图01:【数组】项目的设计界面

  9. 把Visual Studio .Net的当前窗口切换到【Form1.vb】,进入Form1.vb文件的编辑界面。然后用下列的代码替换Form1.vb中Button1组件的Click事件对应的处理代码,下列代码的功能是通过创建输入对话框来创建一个一维数组:

  Private Sub Button1_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button1.Click

  Dim i As Integer

  For i = 0 To 3

  arrString ( i ) = InputBox ( "请在下面文本框中输入字符串" , "请输入字符串 , 来初始化创建的一维数组!" , "Item " &i )

  Next

  Button3.Enabled = True

  Button4.Enabled = True

  DisplayArray ( arrString )

  End Sub

  10. 用下列的代码替换Form1.vb中Button2组件的Click事件对应的处理代码,下列代码的功能是创建一个二维数组,并进行初始化:

  Private Sub Button2_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button2.Click

  Dim arrDate ( , ) As String = {{"星期一" , "18号"} , {"星期二" , "19号"}}

  '创建一个二维数组,并初始化

  MsgBox ( arrDate ( 0 , 1 ) )

  '访问这个二维数组中的元素

  End Sub

  11. 用下列的代码替换Form1.vb中Button3组件的Click事件对应的处理代码,下列代码的功能是首先定义一个名称为“DisplayArray”的过程,此过程能够对给定的一维数组中的数据进行排序,并通过ListBox显示出来。其次是定义Button3的Click事件,在此事件中对调用DisplayArray过程,对一维数组中的数据进行排序:

  '定义一个过程,过程的功能是通过ListBox组件显示给定的字符串数组中各元素

  Sub DisplayArray ( ByVal myString ( ) As String )

  ListBox1.Items.Clear ( )

  Dim Temp As String

  For Each Temp In myString

  ListBox1.Items.Add ( Temp )

  Next

  End Sub

  Private Sub Button3_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button3.Click

  Array.Sort ( arrString )

  DisplayArray ( arrString )

  End Sub

12. 用下列的代码替换Form1.vb中Button4组件的Click事件对应的处理代码,下列代码的功能是重新定义一维数组:

  Private Sub Button4_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button4.Click

  ReDim Preserve arrString ( 5 )

  '请注意Preserve关键字的作用

  Dim i As Integer

  For i = 4 To 5

  arrString ( i ) = InputBox ( "请在下面文本框中输入字符串" , "请输入字符串 , 来初始化重新创建的一维数组!" , "Item " &i )

  Next

  DisplayArray ( arrString )

  End Sub

  13. 保存上面的所有修改,至此【数组】项目的全部工作就完成了。此时单击快捷键F5运行程序,图02、图03是程序编译后的运行界面:

在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件

图02:输入字符串来初始化一维数组的界面

在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件

图03:对一维数组中的各元素进行排序后的界面

  八.总结:

  本文首先介绍了Visual Basic .Net中的数组和原先版本的Visual Basic中的区别,在Visual Basic .Net中数组从内涵上更像Visual C#。其次介绍了数组的申明方法,其中包括一维数组、多维数组,也包括静态数组和动态数组,初始化数组,及其访问数组中的元素。接着介绍了重新申明数组方法,即ReDim语句的使用用法,及其Preserve关键字的作用。以及使用For Each …. Next语句来遍历数组中各个元素,For Each …. Next语句是操作数据最为常用的一种语句,它能够方便的访问到数组中的每一个元素。比用For ……Next语句要方便了许多。最后介绍在以数组为参数的过程和函数的调用方法,和Array类和其主要的使用方法。之所以提出来介绍以数组为参数的过程和函数的调用方法,是因为数组是引用类型,所以在申明参数为数组的函数或过程时,处理方法与参数为值类型的函数或过程有点不一样。Array是.Net FrameWorkSDK中提供用来操作数组的类,本文主要是介绍利用Array类操作数组的具体方方法法。以上就是本文的主要内容,相信仔细阅读并进行相应练习的读者一定已经掌握了。


我们都知道在所有程序设计语言中数组都是一个非常重要的概念,数组的作用是允许程序员用同一个名称来引用多个变量,因此采用数组索引来区分这些变量。很多情况下利用数组索引来设置一个循环,这样就可以高效地处理复杂的情况,因此在很多情况下,使用数组可以缩短或者简化程序的代码。本文主要介绍VB.NET数组的使用,希望对大家的使用带来帮助。


数组中的第一个元素的下标称为下界,最后一个元素的下标称为上界,其余的元素连续地分布在上下界之间,并且数组在内存中也是用连续的区域来存储的,所以要求声明数组每维的长度不能超过Long数据类型的最大值,即264—1=263。

我们把VB.NET数组当作一个对象来处理,这就意味着数组类型是单个引用类型,数组变量包含指向构成数组元素、数组维和数组长度等数据的指针,数组之间互相赋值其实只是在相互复制指针,而且数组继承了System名字空间的Array类。

VB.NET中提供的数组类型和VB 6.0中有一些差别,我们将在下面做详细的讲解。

(1)VB.NET数组的声明

VB.NET中的数组有两种类型:定长数组和动态数组。这里先介绍定长数组的几种不同的声明方式,不同的声明方法将导致数组不同的有效范围。

◆Dim语句在模块段建立模块级数组,例如:

  • Dim arrayl(3)As Integer

◆Public语句在模块的声明部分建立一个公共数组,例如:

  • Public counttype(20)as string

◆Static语句声明一个过程内的局部数组,例如:

  • Public Sub Ipaddress()
  • Static server(30)as string
  • End Sub

VB.NET还提供了新的数组初始化语法,只需要简单的语句就可以完成数组的声明和初始化,例如:

  • New array initialization syntax
  • Dim arrayl As Integer()={2,4,8}

在VB.NET中,为了和其他语言更加易于协同操作,数组的下标均设定为0,不允许声明一个下界为1的数组,因此Option Base语句不再被VB.NET支持,而且在声明一个数组时必须用它的元素个数,而不是它的上界来初始化,例如:

  • //声明一个一维数组具有3个元素,下标从0~2
  • Dim arrayl(3)As Integer
  • arrayl(0):2
  • arrayl(1)=4
  • arrayl(2)=8

以上声明的数组有三个元素,下标从0到2,如果代码企图访问下标为3的数组元素,将引起运行错误。

(2)二维数组及多维数组

除了较为简单的一维数组外,VB.NET还支持多维数组,其声明方法和一维数组没有太大的区别,例如:

  • StatiC multidim(10,10)as double
  • Public Singledim(5,8,10,3)as single

以上语句声明了一个lO行,10列的二维数组。在VB.NET中,数组最多有32维,而且每一维的长度都不能够超过Long数组类型的最大值。数组总尺寸的限制是不一样的,这与所采用的操作系统以及计算机中使用的内存量有关。数组的维数将保留在System.Array.Rank属性中,每维的长度可以由System.Array.GetLengfll方法来得到。需要提醒注意的是,由于VB.NET中数组是以0为基的,如果返回来的值为9,则表示数组是10维的。当为数组继续添加维数的时候,使其扩展为多位数组,此时会使数组所需的存储空间大幅度增加,所以在使用多维数组时对这个方面也要多加考虑。

另外VB.NET还提供了Lbound()和Lbound()两个函数来返回数组的上、下界。中国自学编程网整理发布 ,www.zxbc.cn对于一维数组而言,只需要一个参数,那便是数组名。例如:

  • one==Ubound(arrayl)

对于多位数组,也只是简单地将逗号后面的第二个参数指定为数组的第几维。例如:

  • tw0=Lbound(multidim,7)

如果没有指明是哪一维,系统默认为第一维。

(3)动态数组

有时在程序运行之前无法确认数组的大小,VB.NET提供了在程序运行时动态决定数组大小的功能,即动态数组。它具有灵活多变的特点,可以在任何时候根据需要随时改变数组的大小,有助于内存的管理。建立一个动态数组的详细步骤如下:

①和声明一般数组一样,可以使用前面介绍的几种声明,只是赋一个空维数组,这样就将数组声明为动态数组。典型的声明语句为:

  • Dim types(  )  As integer

②然后使用ReDim语句来配置数组大小。ReDim语句声明只能在过程当中使用,它是可执行语句,可以改变数组中元素的个数,但是却不可以改变数组的维数,就是说不能把一维变为二维。在ReDim语句配置数组元素个数时,数组中的内容将全部置为0。典型语句为:

  • ReDim Types(X+1)

③如果想改变数组大小又不想丢失原来的数据,只要在ReDim语句中包含Preserve关键字就可以,典型语句为:

  • ReDa_m PresetVe Types(10,23)

对于多维数组,在使用Preserve关键字时,只能修改最后一维的大小。如果改变其他维,那么将出现运行错误。如果不清楚某维的当前大小,可以使用GetI~ength函数来获取。

(4)VB.NET数组的使用

在’VB 6.0中,可以用For Each来循环遍历一个数组。例如:

  • Dim x As Integer
  •   F0r Each x In arrayl
  •   Console.WriteLine(x)
  •   Next

在VB.NET中可以使用For循环和数组长度来遍历一个数组。例如:

  • Dim i As工nteger
  •    F0r i=0 T0  (arrayl.Length-1)
  •    Console.WriteLine(arrayl(1)J
  •    Next i

在使用数组时还要注意,不仅声明语法有变化,而且在运行时处理方式也有了很大的变化。VB.NET在堆栈中给数组分配地址空间,当向一个方法传递数组类型的参数时,使用的是引用传递而不是值传递。下面是互相传递数组引用的三个方法:

  • Dim arrayl(3,3)AS Integer
  •     Dim array2 As Integer(,)
  •     Redim array2(3,3)
  •     Dim array3 As Integer(,)={{2,4},{12,29}}

方法一在两个方向同时传递了数组引用,一般用来向调用者返回数组引用。方法二和方法三从调用者向方法的实现中传递了数组引用。方法二的参数被声明为一维数组,而在方法三中参数被声明成了-维数组。

(5)数组的高级特性

①数组的数组

在O~ect数组中还可以组装不同类型的数组。例如,以下代码中先建立两个数组,一个是Integer类型,另一个是String类型,然后再声明一个O~ect类型的数组,把前两个数组分装在其中。

  • Dim I as integer
  • //声明一个integer类型的数组
  • Dim grade(15)as integer
  • For i:0 tO 14
  • Grade(i)=i
  • NeXt i
  • //声明一个string类型的数组
  • Dim name(15)as String
  • For i=0 tO 14
  • Name(i):”Student”&cstr(i)
  • Next i
  • //声明一个新的数组为object,用来组装其他数组
  • Dim Student(2)as object
  • Student(0)=grade
  • Student(1)=name
  • Msgbox(student(0)(2))  //显示”2”
  • Msgbox(student(1)(3))  //显示”student 3”。

上述代码中使用了student(0)和student(1)的后绑定。注意,只有在Option s~ict被关闭时,VB.NET编译器才允许使用后绑定。

②数组和集合

虽然集合通常用于操作对象,但是它也能操作数据类型。在某些条件下,其效率比数组还要高。我们可以通过以下4个方面来进行比较。

◆集合可以根据需要进行扩充,不像数组那样需预先规定大小。

◆数组只能保存声明时所定义的数据类型,但是同一个集合中可以存储不同类型的数据。

◆集合元素的修改较为麻烦,不像数组那么方便。

◆处理集合的速度较数组慢,但是在处理较小的动态条目集,使用集合是最为理想的选择。


变量、数组、集合、泛型的发展

           最开始用内存中一个位置映射一个值,用变量来“使用”这个值。

           进一步发展,用变量来引用一组值,这就是数组。由数组概念,发展出链表、堆、栈,进行排序、检索等。

           但这并不能完全表达,由此发展出集合概念,它是更强大的数组,都依赖于Object基类。

           随之而来的是集合中元素并不一定是一样的,于是都得转为Object,涉及到装箱,使性能下降,特别是元素量巨大时。而且

                          由于我们一般使用同一类型(强类型)更方便操作。由此产生了泛型

           泛型简单地说,就是把里面的元素强制指定为特定的类型,也可以说是模板。







一、数组


1、数组的定义      

         System.Array类是数组的基础,数组就是由它派生而来。

         所有.Net数组和集合的下标总是从0开始。故元素的个数是上限+1

         数组的定义:


[vb] view plain copy
print?


  • Dim a1(20) As Integer  
  • Dim a2() As Integer = {1, 2, 3, 4}  
  • Dim a3(4, 2) As Integer  
  • Dim a4(,) As Integer = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}, {13, 14, 15}}  
  • Dim a5() As Integer  

        a1数组是从a1(0)到a1(20)共21个元素,而不是20个元素。20表示上限。

        a2表示4个元素,上限是3,即a2(3)

        a3表示的是二维数组

        a4也是二维,但其一维和二维的上限由后面的值来确定。

        a5表示是不定数组,将在后面的使用中来确定,它是一个重要的概念





2、多维数组

       UBound用来提取数组中某维中的上限(注意不是个数),LBound是提取数组的下限,由于下限永远是从0开始,所以这个函数没用了。

        另外维数是从左到右,从1开始计数(这与元素索引从0开始计数不同)

        需要注意的是: GetUpperBound(0)也是提取上限,例如 :  a1.GetUpperBound(0)

                                     它的维数却是以0开始,相当于UBound中维数的1


[vb] view plain copy
print?


  • Module Module1  
  •   
  •     Sub Main()  
  •         Dim a(,) As Int32 = {{1, 2, 3}, {3, 4, 5}, {6, 7, 8}}  
  •         Dim temp As Int32  
  •         For i As Int32 = 0 To UBound(a)  '即UBound(a,1)  
  •             For j As Int32 = 0 To UBound(a, 2) '将返回其最大可用下标的维度。 对第一维使用 1,对第二维使用 2,  
  •                 temp += a(i, j)                '依此类推。 如果省略 Rank,则假定为 1。  
  •             Next  
  •         Next  
  •         Console.WriteLine(temp)  
  •         Console.Read()  
  •     End Sub  
  •   
  • End Module  




3、不定数组

       就是声明时并没有实例化的数组,它只是说明了类型,却没有在内存中分配空间(因为元素个数未定)

       因此,它没有具体实例化前是不能直接使用的,如图,出错:

       在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件


       未处理,其值为空。



       ReDim

         不定数组在使用前须用ReDim来实例化(指明个数,以便分配内存空间),但不得改变成其它类型,否则出错。


[vb] view plain copy
print?


  • Sub Main()  
  •         Dim a() As Int32  
  •         ReDim a(3) '只能实例化,不能声明(成类型)  
  •         Console.WriteLine(a(0))  
  •         Console.Read()  
  • End Sub  

        注意:ReDim与VB6中不同:(1)须先声明类型,再用ReDim,不能用ReDim来声明(成其它类型)

                                                              (2)不能改变数组维数(增加或减少都不行)



         Preserve

         保持之意。不定数组经ReDim实例化后,还可再次用ReDim来改变,第二次改变会直接改变第一次实例化中重叠的元素。

          为了保持元素值,用Preserve来指明。

          注意Preserve只能修改最后一维的大小。


[vb] view plain copy
print?


  • Sub Main()  
  •     Dim a(,) As Int32  
  •     ReDim a(6, 5)  
  •     a(6, 1) = 3  
  •     ReDim a(7, 4)        '正确,无Preserve时,可以修改多维   
  •     'ReDim Preserve a(5, 4) '错误,有Preserve时,只能修改最后一维的大小  
  •     Console.WriteLine(a(6, 1))  
  •     Console.Read()  
  • End Sub  









二、集合


             数组功能很强大,但Array基类并没为数组提供更多的功能,比如排序、动态分配内存。为了更强大的功能产生了集合。


            集合(Collections)名称空间是System名称空间的一部分,它提供系列高级功能。

            对不同的用处,System.Collections名称空间提供了几个强大的类:

                      ArrayList    实现一个数组,其大小在添加元素时自动增加大小(不必烦恼数组的上限或用ReDim、Preserve)

                      BitArray      管理以位值存储的布尔数组

                      Hashtable   实现由键组织的值的集合(Key,Value),排序是基于键的散列完成的(哈希函数)

                      Queue         实现先进先出集合(排序方式)

                      Stack            实现后进先出集合

                      SortedList    实现带有相关的键的值的集合,该值按键来排序,可以通过键或索引来访问



1、ArrayList  数组列表

             ArrayList 仅一维且不保证是排序的。 可使用一个整数索引访问此集合中的元素。 此集合中的索引从零开始。

             在执行需要对 ArrayList 排序的操作(如 BinarySearch)之前,必须对 ArrayList 进行排序。

           ArrayList 的容量是 ArrayList 可以包含的元素数。 随着向 ArrayList 中添加元素,容量通过重新分配按需自动增加。
           可通过调用 TrimToSize 或通过显式设置 Capacity 属性减少容量。对于非常大 ArrayList 对象,则在运行时环境
          (ide) 中增加最大容量为 20亿在 64 位系统的元素通过设置 gcAllowVeryLargeObjects 配置元素的 enabled 属性设置为 true 。

            ArrayList 集合接受 null 引用(在 Visual Basic 中为 Nothing) 作为有效值并且允许重复的元素。


[vb] view plain copy
print?


  • Module Module1  
  •   
  •     Sub Main()  
  •         '使用大小会根据需要动态增加的数组来实现 IList 接口  
  •         Dim objArryList As New System.Collections.ArrayList  
  •         Dim objItem As Object  
  •         Dim intLine As Int32 = 1  
  •         Dim strHello As String = "Hello"  
  •         Dim objWorld As New System.Text.StringBuilder("World")  
  •   
  •         objArryList.Add(intLine)  
  •         objArryList.Add(strHello)  
  •         objArryList.Add(" "c)  
  •         objArryList.Add(objWorld)  
  •         objArryList.Insert(1, ". ") '在索引1处插入。(索引从0开始)  
  •   
  •         For Each objItem In objArryList  
  •             Console.WriteLine(objItem.ToString)  
  •         Next  
  •         Console.Read()  
  •     End Sub  
  •   
  • End Module  

          可以看到使用很方便:1、不需要声明数组大小

                                                   2、不需要重写定义数组大小

                                                   3、不需要用Preserve来保持数据

          ArrayList都会自动完成这样的功能。





2、Hashtable  哈希表

         表示根据键的哈希代码进行组织的键/值对的集合。

         键通过一个哈希函数来确定元素值的具体存储位置。这样就可以快速由Key取得值。

         键不能是Nothing(NULL),值可以是。

         优点:定位查找一个值,插入、删除一个映像的效率最高。




3、SortedList  排序列表
             hashtable是没有排序的,所以新增元素会比较快。而SortedList 存储的键值对,是按key进行排序了的,

            因为要排序,所以新增元素时,要先查找元素的位置再插入,相对慢些,但是在查找时比较快。

            下面,每变动一次元素,自动会按Key进行排序,所以最后不需排序,就可得到排序的结果:

             在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件





4、Queue 队列

           表示对象的先进先出集合。

          队列在按接收顺序存储消息方面非常有用,以便于进行顺序处理。 此类将队列作为循环数组实现。 存储在 Queue 中的对象在一端插入,从另一端移除。

          Queue 的容量是 Queue 可以包含的元素数。 随着向 Queue 中添加元素,容量通过重新分配按需自动增加。 可通过调用 TrimToSize 来减少容量。

          等比因子是当需要更大容量时当前容量要乘以的数字。 在构造 Queue 时确定增长因子。 默认增长因子为 2.0。 Queue 的容量将始终加 4,

          无论增长因子是多少。 例如,当需要更大的容量时,增长因子为 1.0 的 Queue 的容量将始终增加四倍。

          Queue 接受 null 引用(在 Visual Basic 中为 Nothing) 作为有效值并且允许重复的元素

          在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件





5、Stack 栈

        表示对象的简单后进先出 (LIFO) 非泛型集合

          在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件


         注意:比较与Queue的输出顺序





6、循环控制

      (1)For...Next...

           For Each...Next...

                     越过循环:Contunue For

                     退出循环:Exit For


       (2) While..End While       (更常用)

              Do While...Loop

               Do  Until...Loop

                        同理,越过:Continue While        或Continue Do

                                    退出:Exit While                  或Exit  While


       (3)Thread.Sleep()

             大循环或无限循环中,会一直占用线程,给造成界面假死现象,可用Thread.Sleep(),这样仅在给定时间才执行,以避免

              消耗过多的处理器时间。

                     while   i=1

                                 ....

                                 system.Threading.Thread.Sleep(500)  

                                 ...

                      end while










三、泛型



1、装箱(Boxing)

         (1)什么是装箱?

                  值类型存储在栈上,引用类型存储在堆上。

                  当值类型向引用类型转变,即从栈向堆上转移,这时值就变成了一对象,就好像值类型外面包装了一层东西,这个过程叫装箱(Boxing)  


[vb] view plain copy
print?


  • '不需要装箱,都是值类型  
  • Dim a1(20) As Integer  
  • Dim a2 As Integer = 1  
  •   
  • a1(0) = 0  
  • a1(1) = a2  
  •   
  • '需要装箱,String是引用类型  
  • Dim b1 As New System.Text.StringBuilder()  
  • Dim b2 As New System.Collections.SortedList()  
  • Dim i As Integer  
  •   
  • For i = 1 To 100  
  •     b1.Append(i) '未装箱,直接接收  
  •     b2.Add(i, i) '装箱,参数需要两个对象,要转换integer为对象  
  • Next  




           (2)装箱的影响

                    显然装箱会使“值”的外层多了一些“无用”的东西,会使得性能稍有下降。

                    集合中元素都来自Object(引用类型),即,它是在堆上,都涉及到一个装箱,如果数据量大时,性能下降得就可观了。

                   当需要时其中的“值”时,又需要把箱子,从堆上转移到栈上,即引用类型变成值类型,这个过程叫拆箱。



             (3)为什么要有泛型?

                     集合中,任何引用或值类型都将隐式地向上强制转换为Object。如果项是值类型,添加到列表中时,进行装箱操作,在检索时进行取消装箱操作。

                     这样,强制转换以及装箱和拆箱操作都会降低性能。

                     另一个限制是缺少编译时类型检查。同一个集合可接收不同类型,所有项都强制转换为 Object,在编译时无法检查是否可以收这种类型,还是人为

                     错误输入了另一个类型,同时智能感应只会提示Object的方式,使得检查错误变得艰难。


                    如果我们对其中的类型进行一些限制,使之成为统一的类型,虽然稍微增加了编码的复杂性,但好处是可以创建一个 更安全并且速度更快的列表,

                    校验错误也变得容易。


                     鉴于这种情况,催生了泛型的产生。




2、泛型的使用

         泛型主要的目的是创建强类型化的集合,使处理速度加快。所以前面使用Object的普通集合类,最好使用泛型。

         泛型内置于.net中,允许定义代码模板,然后使用这个模板声明变量,它实际上是创建了一个新的数据类型。


         .net基类库(BCL)里有许多泛型模板,多位于System.Collections.Generic名称空间,也有分布在其它BCL中。


          泛型带来的性能提升,可以让任何使用集合数据类型的地方都应当使用泛型代替。


           泛型通常使用List(of   T)形式,List是类型(或者类)的名称 ,字母T是点位符类似于参数。它表示 必须提供一个用来定制泛型

           的特定类型值,同时也限定的它只能是这个类型。


[vb] view plain copy
print?


  • Dim data1 As New List(Of Date) '元素只能是Date类型  
  • '===================================  
  • Dim data2 As New ArrayList  '未限定元素类型,任意。(object)  
  • data2.Add(5)  
  • data2.Add("xxx")  
  • data2.Add(3.2)  
  • For Each i As Object In data2  
  •     TextBox1.AppendText(i.ToString & Environment.NewLine)  
  • Next  


             上面可以看到,当没有限定时,它是Object,因为可能是integer,String,double等,最终将转向Object。也就是说

              普通集合中元素是多种情况,只有当用了泛型才进行了统一,这样处理更快。


               当用了泛型后,类型参数指明后,将不能再用其它类型,如下:


[vb] view plain copy
print?


  • Dim data1 As New List(Of Integer) '元素只能是Integer类型  
  • data1.Add(33)           '正确  
  • data1.Add("Hello")      '错误,不能为string  


               泛型有两种形式:泛型类型和泛型方法

                        List(of  T)是泛型类型,定义了完整的类型或类的模板。

                        泛型 方法是一种方法模板,使用时必须指明方法使用的“具体类型”。




3、Nullabel   可空类型

        简言之:可以有空值的类型。 比如数据库有字段有integer型,但有时是DBNULL(空值),在取时会出错,这个类型就有用处了。

        Nullable不是值类型。


[vb] view plain copy
print?


  • Dim intValue1 As New Nullable(Of Integer) '可为空的Integer类型  
  • Dim intValue2 As Integer?   '与上句等效  
  •   
  • intValue1 = 3  
  • intValue1 = Nothing '可为空,正确  
  • intValue2 = Nothing  





[vb] view plain copy
print?


  • Dim intValue1 As New Nullable(Of Integer) '可为空的Integer类型  
  •   
  • intValue1 = Nothing  
  • If intValue1.HasValue Then '判断是滞有值  
  •     MessageBox.Show("有值")  
  • Else  
  •     MessageBox.Show("空值")  
  • End If  

              在取得这样的类型时,当用判断来说明值的情况。




4、泛型类型

      泛型有两形式:泛型类型、泛型 方法。下面说明泛型类型

         泛型类型是用来定义类、结构、接口的模板。在使用泛型类型声明变量时,需要提供真正(具体)的类型,以确定实际类型。


     (1)泛型的基本用法


[vb] view plain copy
print?


  • Dim data As New Generic.Dictionary(Of Integer, String)  
  •   
  • data.Add(3, "OK")  
  • data.Add(4, "dz")  
  • data.Add(1, "John")  
  •   
  • 'KeyValuePair(Of Integer, String) 键值对元素  
  • For Each o As KeyValuePair(Of Integer, String) In data  
  •     TextBox1.AppendText(o.Key & "," & o.Value & vbCrLf)  
  • Next  
  • '==========================  
  • Dim data2 As New Generic.Dictionary(Of Guid, Date)  
  •   
  • data2.Add(New Guid, Now)  
  • For Each o As KeyValuePair(Of Guid, Date) In data2  
  •     TextBox1.AppendText(o.Key.ToString & "," & o.Value) 'Guid须转String  
  • Next  

           Generic.Dictionary(Of K,T)泛型,与List(Of  T)类型类似,但需两个类型参数来提供键与值(Key,Value)。

           新的Dictionary类型只接受特定类型的键与值,如上面第一个是Integer与String。第二个只接收Guid与Date。



             上面是声明时的情况,下面是作返回值的情况


[vb] view plain copy
print?


  • Private Function reGeneric() As Generic.Dictionary(Of Integer, String) '返回值类型  
  •     Dim data As New Generic.Dictionary(Of Integer, String)  
  •     data.Add(3, "dx")  
  •     data.Add(2, "qxj")  
  •     data.Add(1, "ase")  
  •     Return data  '返回泛型  
  • End Function  


            可以这样调用上面函数:


[vb] view plain copy
print?


  • Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  •     Dim data As New Generic.Dictionary(Of Integer, String)  
  •   
  •     data = reGeneric() '调用,取得泛型  
  •     For Each o As KeyValuePair(Of Integer, String) In data  
  •         TextBox1.AppendText(o.Key & "," & o.Value & vbCrLf)  
  •     Next  
  • End Sub  


          泛型还可以作为传参:


[vb] view plain copy
print?


  • Private Sub useGeneric(ByVal k As Generic.Dictionary(Of Integer, String)) '泛型作参数  
  •     'add code  
  • End Sub  



         (2)继承

             定义新类时,可以继承泛型类型。

             例如:.net BCL定义的System.ComponentModel.BindingList(Of  T)泛型类型,它用于创建支持数据绑定的集合。

                          可以将其作用基类,创建支持数据绑定的强类型集合。


[vb] view plain copy
print?


  • Public Class Form1  
  •     Dim list As New CustomerList  
  •   
  •     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load  
  •         DataGridView1.DataSource = list  
  •     End Sub  
  • End Class  
  •   
  • Public Class Customer  
  •     Public Property Name() As String  
  • End Class  
  •   
  • Public Class CustomerList  
  •     Inherits System.ComponentModel.BindingList(Of Customer) '必须指明具体的类型(如Customer)  
  •   
  •     Private Sub CustomerList_AddingNew(ByVal sender As Object, ByVal e As System.ComponentModel.AddingNewEventArgs) Handles Me.AddingNew  
  •         Dim cust As New Customer  
  •         cust.Name = "<new>"  
  •         e.NewObject = cust  
  •     End Sub  
  • End Class  

        上面继承时,必须指明具体类型,于是可以用BindingList(Of  Customer)

        常规继承概念也可以用在其中,比如:重载、重写、事件等。

             在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件






5、泛型方法

         泛型方法语法较复杂,较难理解。在调用泛型方法时,要使用定义该方法的类型参数外,还可以使用普通参数。


         泛型方法不必只在定义的泛型类型中使用,还可以任意的类型和模块中使用泛型方法。

          泛型方法的好处是:不需要使用Ctype或DirectCast转换不同类型的参数与返回值。(因为泛型是CType与DirectCast替换的机制,它实际上仍然会转换)


           下面重载泛型方法:


[vb] view plain copy
print?


  • Public Class Form1  
  •     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  •         Dim result As Boolean  
  •         result = AreEqual(1, 2)  
  •         result = AreEqual("one", "two")  
  •         result = AreEqual(1, "two") '均正确写法,转为object比较  
  •   
  •         '使用泛型  
  •         result = AreEqual(Of Integer)(1, 2)  
  •         result = AreEqual(Of String)("one", "two") '正确写法  
  •         result = AreEqual(Of Integer)(1, "two") '错误  
  •     End Sub  
  •   
  •     '不使用泛型  
  •     Public Function AreEqual(ByVal a As Object, b As Object) As Boolean  
  •         Return a.Equals(b)  
  •     End Function  
  •   
  •     '使用泛型(重载)  
  •     Public Function AreEqual(Of T)(ByVal a As T, b As T) As Boolean  
  •         Return a.Equals(b)  
  •     End Function  
  • End Class  

           泛型方法会有两套参数(分别用两个括号):

                  第一套参数(第一个括号)用来定义方法中使用的类型

                  第二套参数(第二个括号)与我们平时的参数列表一样,只不过用T等来代替要用的类型。

           上面如果在Option  Strict On时






6、创建泛型类型

        通过前面感性认识了:泛型类型与泛型 方法。


         泛型类型是定义类、结构、接口的模板,通过创建模板获得更好性能实现代码重用。



       (1)泛型类

            创建泛型类模板与创建普通类类似,但前者要求提供使用的类型,这样在使用时以便明确这个类型:


[vb] view plain copy
print?


  • '创建泛型类(定义)  
  • Public Class SingleLinkedList(Of T) 'T可自定,但在使用中,声明时须指定明确的类型  
  •     'add code  
  • End Class  

           上面在使用(声明)中,就须指明T的具体类型,T与变量命名方式一样。


           下面创建链表,为了适合不同类型情况,使用泛型。在这个嵌套类中先定义结点类Node:


[vb] view plain copy
print?


  • Public Class SingleLinkedList(Of ValueType) '单向链表类。其中,自定类型ValueType  
  • #Region "Node Class"  
  •     Public Class Node '每个结点由当前值、指向下一个结点的引用,这两个元素组成  
  •         Private mValue As ValueType  
  •   
  •         Public ReadOnly Property Value() As ValueType '当前结点的值  
  •             Get  
  •                 Return mValue  
  •             End Get  
  •         End Property  
  •         Public Property NextNode() As Node '下个结点的引用  
  •         Public Sub New(ByVal value As ValueType, ByVal newNode As Node) '创建新结点  
  •             mValue = value  
  •             NextNode = newNode  
  •         End Sub  
  •     End Class  
  • #End Region  
  • End Class  


      这样在声明使用中就可以使用具体类型,比如用Double类型的链表:

        Dim list As New SingleLinkedList(Of Double)
      这时,在类的的ValueType实际上就变成了:
        Private mValue As Double


        实际上,在设计时(ValueType类型),被当作了Object(类型),故只能使用System.object类型上的方法:

                     Equals()、  GetHashValue()、     GetType()、   ReferenceEquals()、    Tostring()

        这将限制我们操作,并且智能化提示也受限,后面将用约束概念,来明确选择的类型,这样扩展功能增强智能化提示。


         然后,使用Node完善链表类:        


[vb] view plain copy
print?


  • Public Class SingleLinkedList(Of ValueType) '单向链表类。其中,自定类型ValueType  
  • #Region "Node Class"  
  •     Public Class Node '每个结点由当前值、指向下一个结点的引用,这两个元素组成  
  •         Private mValue As ValueType  
  •   
  •         Public ReadOnly Property Value() As ValueType '当前结点的值  
  •             Get  
  •                 Return mValue  
  •             End Get  
  •         End Property  
  •         Public Property NextNode() As Node '下个结点的引用  
  •         Public Sub New(ByVal value As ValueType, ByVal newNode As Node) '创建新结点  
  •             mValue = value  
  •             NextNode = newNode  
  •         End Sub  
  •     End Class  
  • #End Region  
  •   
  •     Private mHead As Node '头结点,也是当前结点。(按倒序加入结点,参看后图)  
  •   
  •     Default Public ReadOnly Property Item(ByVal index As Integer) As ValueType '获取第N个结点值  
  •         Get  
  •             Dim current As Node = mHead  
  •             For i As Integer = 1 To index  
  •                 current = current.NextNode  
  •                 If current Is Nothing Then  
  •                     Throw New Exception("Item not found in list")  
  •                 End If  
  •             Next  
  •             Return current.Value  
  •         End Get  
  •     End Property  
  •   
  •     Public Sub Add(ByVal value As ValueType) '添加结点到链表  
  •         mHead = New Node(value, mHead)  
  •     End Sub  
  •   
  •     Public Sub Remove(ByVal value As ValueType) '从链表中移除结点  
  •         Dim current As Node = mHead  
  •         Dim preNode As Node = Nothing  
  •   
  •         While current IsNot Nothing  
  •             If current.Value.Equals(value) Then  
  •                 If preNode Is Nothing Then '是否为头结点  
  •                     mHead = current.NextNode  
  •                 Else  
  •                     preNode.NextNode = current.NextNode '非头结点(参看下图)  
  •                 End If  
  •                 Exit Sub '已移除,退出  
  •             End If  
  •             preNode = current  
  •             current = current.NextNode  
  •         End While  
  •         Throw New Exception("Item not found in list") '链表中未找到  
  •     End Sub  
  •   
  •     Public ReadOnly Property Count() As Integer '统计结点数  
  •         Get  
  •             Dim result As Integer = 0  
  •             Dim current As Node = mHead  
  •             While current IsNot Nothing  
  •                 result += 1  
  •                 current = current.NextNode  
  •             End While  
  •             Return result  
  •         End Get  
  •     End Property  
  • End Class  

在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件



           定义好链表类后,下面使用:


[vb] view plain copy
print?


  • Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  •     Dim list As New SingleLinkedList(Of String)  
  •   
  •     list.Add("one")  
  •     list.Add("two")  
  •     list.Add("three")  
  •     list.Add("sichuan")  
  •     list.Add("dazhou")  
  •     TextBox1.Clear()  
  •     TextBox1.AppendText(list.Count & vbCrLf)  
  •     For i As Integer = 0 To list.Count - 1 '这里只能从0,因为你不能预知是否有结点。  
  •         TextBox1.AppendText(list.Item(i) & vbCrLf)  
  •     Next  
  • End Sub  

         运行,结果如下:

            在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件





     (2)泛型类的其它功能

              Dictionay泛型有多个类型参数,还可带其它普通类型:


[vb] view plain copy
print?


  • Public Class MyType1(Of T, V) '带两个类型参数  
  •     Private mValue As T  
  •     Private mData As V  
  •   
  •     Public Sub New(ByVal value As T, ByVal data As V) '带两个类型参数  
  •         mValue = value  
  •         mData = data  
  •     End Sub  
  • End Class  
  •   
  • Public Class MyType2(Of T, V)  
  •     Private mValue As T  
  •     Private mData As V  
  •     Private mMoney As Double  
  •   
  •     Public Sub New(ByVal value As T, ByVal data As V, ByVal money As Double) '带两个类型参数及一个普通类型参数  
  •         mValue = value  
  •         mData = data  
  •         mMoney = money  
  •     End Sub  
  • End Class  





        (3)类、泛型类与继承

          泛型类实际上是一种特殊的类。因此也具有继承等特点。

          泛型类可以继承现成的类,普通类也可继承泛型类,泛型类可以继承泛型类。还有复杂的泛型子类传回泛型父类。


[vb] view plain copy
print?


  • '泛型继承现成的类  
  • Public Class MyControls(Of T)  
  •     Inherits Control  
  • End Class  
  •   
  • '基类泛型  
  • Public Class GenericBase(Of T)  
  •     'add code  
  • End Class  
  •   
  • '类继承泛型  
  • Public Class SubClass  
  •     Inherits GenericBase(Of Integer) '必须指明类型  
  •     'add code  
  • End Class  
  •   
  • '泛型继承泛型(不同类型)  
  • Public Class GenericSubClass1(Of T)  
  •     Inherits GenericBase(Of Integer) '必须指明类型  
  •     'add code  
  • End Class  
  •   
  • '泛型继承泛型  
  • Public Class GenericSubClass2(Of V) '在使用时(声明)指明V类型  
  •     Inherits GenericBase(Of V)  '与上V相同,故类型由子类传递回父类  
  •     'add code  
  • End Class  
  •   
  • '复杂子类泛型传递回父类  
  • Public Class GenericSubClass3(Of V)  
  •     Inherits GenericBase(GenericBase(of V)) '子类型传回父类  
  •     'add code  
  • End Class  




           (4)结构、接口中使用泛型

            结构与类一样,在结构中也可以使用泛型:


[vb] view plain copy
print?


  • '结构中使用泛型   
  • Public Structure MyCool(Of T)  
  •     Public value As T  
  • End Structure  

             这样,在使用时就可以:   Dim  data  as MyCool(Of   Guid)


            还可以定义泛型类接口类型。

             泛型接口与泛型类、泛型结构有所不同:它的实现依赖其它类型:


[vb] view plain copy
print?


  • '接口使用泛型  
  • Public Interface Icool(Of T)  
  •     Sub DoWork(ByVal data As T)  
  •     Function GetAnswer() As T  
  • End Interface  
  •   
  • Public Class ARegularClass  
  •     Implements Icool(Of String) '必须指明类型  
  •     Implements Icool(Of Integer)  
  •   
  •     '============String时情况==============  
  •     Public Sub DoWork(data As String) Implements Icool(Of String).DoWork  
  •         'add code  
  •     End Sub  
  •   
  •     Public Function GetAnswer() As String Implements Icool(Of String).GetAnswer  
  •         'add code  
  •     End Function  
  •   
  •     '==========Integer时情况=================  
  •     Public Sub DoWork1(data As Integer) Implements Icool(Of Integer).DoWork  
  •         'add code  
  •     End Sub  
  •   
  •     Public Function GetAnswer1() As Integer Implements Icool(Of Integer).GetAnswer  
  •         'add code  
  •     End Function  
  • End Class  

        上面泛型接口定义中无法明确类型,它依赖于ARegularClass中接口类型的定义(有两个:Integer、String)







7、创建泛型方法

      泛型方法也可以泛型类(类、结构、接口)中实现。

       也可以在普通(类、结构、接口、模块)中实现,只不过此时的类型参数是在方法指定(而不是在类、结构、接口上指定)


       下面泛型 方法在普通中,故类型直接在方法中指定(T):


[vb] view plain copy
print?


  • '模块中使用泛型  
  • Public Module Comparisons1  
  •     Public Function AreEqual(Of T)(ByVal a As T, ByVal b As T) As Boolean  
  •         Return a.Equals(b)  
  •     End Function  
  • End Module  
  •   
  • '类中使用泛型  
  • Public Class Comparisons2  
  •     Public Function AreEqual(Of T, R)(ByVal a As T, ByVal b As R) As R '返回也可为R  
  •         'add code  
  •     End Function  
  • End Class  








四、约束(限制)

              泛型类型、泛型方法在编写代码时,类型参数都被当作System.Object类型处理,这限制了使用类型参数的参数与变量的功能。

             即,只能进行赋值和调用所有System.Object变量的几个方法,大大限制了泛型的用途。


             约束就是来突破这种限制,并提供控制机制。约束提供指定规则,声明运行时可以代替类型参数类型。

             使用约束,可以限定类型参数必须是一个类或结构,也可限定类型参数必须实现接口或继承某基类。这样智能提示就生效了。


           通俗地说:约束暗示了某具体类型,使得智能提示生效。





1、类型约束

         这是常用约束,它限制某类型参数必须是指定类的子类或者必须实现指定的接口。

         改变上面的链接类成为ComparableLinkedList,这里泛型指明了ValueType,同时也指明它是一个接口IComparable。

         因此,智能提示会对ValueType类型提示IComparable的属性和方法:


[vb] view plain copy
print?


  • Public Class Form1  
  •     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click  
  •         Dim list As New ComparableLinkedList(Of String)  
  •   
  •         list.Add("one")  
  •         list.Add("two")  
  •         list.Add("three")  
  •         list.Add("sichuan")  
  •         list.Add("dazhou")  
  •         TextBox1.Clear()  
  •         TextBox1.AppendText(list.Count & vbCrLf)  
  •         For i As Integer = 0 To list.Count - 1 '这里只能从0,因为你不能预知是否有结点。  
  •             TextBox1.AppendText(list.Item(i) & vbCrLf)  
  •         Next  
  •     End Sub  
  • End Class  
  •   
  •   
  • Public Class ComparableLinkedList(Of ValueType As IComparable) '类型参数同时也是接口(用于比较)  
  • #Region "Node Class"  
  •     Public Class Node  
  •         Private mValue As ValueType  
  •         Public ReadOnly Property Value() As ValueType  
  •             Get  
  •                 Return mValue  
  •             End Get  
  •         End Property  
  •         Public Property NextNode() As Node  
  •         Public Sub New(ByVal value As ValueType, ByVal newNode As Node)  
  •             mValue = value  
  •             NextNode = newNode  
  •         End Sub  
  •     End Class  
  • #End Region  
  •   
  •     Private mHead As Node  
  •     Default Public ReadOnly Property Item(ByVal index As Integer) As ValueType  
  •         Get  
  •             Dim current As Node = mHead  
  •             For i As Integer = 1 To index  
  •                 current = current.NextNode  
  •                 If current Is Nothing Then  
  •                     Throw New Exception("Item not found in list")  
  •                 End If  
  •             Next  
  •             Return current.Value  
  •         End Get  
  •     End Property  
  •   
  •     '=========这是原来不是接口时的添加元素的方法=========  
  •     Public Sub Add1(ByVal value As ValueType)  
  •         mHead = New Node(value, mHead)  
  •     End Sub  
  •   
  •     '======现在类型参数同时是接口(可用于比较)的方法=====  
  •     Public Sub Add(ByVal value As ValueType)  
  •         If mHead Is Nothing Then  
  •             mHead = New Node(value, mHead) '链表无结点时,直接添加  
  •         Else  
  •             Dim current As Node = mHead  
  •             Dim preNode As Node = Nothing  
  •             While current IsNot Nothing  
  •                 If current.Value.CompareTo(value) > 0 Then '===关键,接口使用(比较)  
  •                     If preNode Is Nothing Then  
  •                         mHead = New Node(value, mHead) '链表头  
  •                     Else  
  •                         preNode.NextNode = New Node(value, current) '链表中  
  •                     End If  
  •                     Exit Sub  
  •                 End If  
  •                 preNode = current  
  •                 current = preNode.NextNode  
  •             End While  
  •             preNode.NextNode = New Node(value, Nothing) '链表尾  
  •         End If  
  •     End Sub  
  •   
  •     Public Sub Remove(ByVal value As ValueType)  
  •         Dim current As Node = mHead  
  •         Dim preNode As Node = Nothing  
  •   
  •         While current IsNot Nothing  
  •             If current.Value.Equals(value) Then   
  •                 If preNode Is Nothing Then  
  •                     mHead = current.NextNode  
  •                 Else  
  •                     preNode.NextNode = current.NextNode  
  •                 End If  
  •                 Exit Sub  
  •             End If  
  •             preNode = current  
  •             current = current.NextNode  
  •         End While  
  •         Throw New Exception("Item not found in list")  
  •     End Sub  
  •     Public ReadOnly Property Count() As Integer  
  •         Get  
  •             Dim result As Integer = 0  
  •             Dim current As Node = mHead  
  •             While current IsNot Nothing  
  •                 result += 1  
  •                 current = current.NextNode  
  •             End While  
  •             Return result  
  •         End Get  
  •     End Property  
  • End Class  


             在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件



           由于上面同时是接口所以可以用CompareTo方法:

                             If current.Value.CompareTo(value) > 0 Then


           上面是限定为接口,下面还可限定为子类(Windows窗体控制Control)

           同时也是在方法中限定(上面是在泛型类型中):


[vb] view plain copy
print?


  • '约束类型参数必须是某类的子类(下例为Control的泛型方法)  
  • Public Shared Sub ChangControl(Of C As Control)(ByVal con As C)  
  •     con.Anchor = AnchorStyles.top Or AnchorStyles.left  
  • End Sub  
  •   
  •   
  •   
  • '===========================================================  
  • '约束类型参数为特定的泛型  
  • Public Class ListClass(Of T, V As Generic.List(Of T))  
  •     'add code  
  • End Class  
  • '使用时这样:  
  • Dim list As ListClass(Of Integer, Generic.List(Of Integer))  

          上面还限制了部分参数须是某泛型类型(V)






2、类、结构的约束

       下面限制类型参数必须是值类型或引用类型:


[vb] view plain copy
print?


  • '约束(限制)类型参数是引用类型  
  • Public Class ReferenceOnly(Of T As Class)  
  •     'add code  
  • End Class  
  •   
  •   
  • '约束(限制)类型参数是值类型  
  • Public Class ValueOnly(Of T As Structure)  
  •     'add code  
  • End Class  






3、New约束

          有时需创建类型参数定义的类型实例,必须使用New约束,来确保该类型有默认的公共构造函数。


[vb] view plain copy
print?


  • Public Class Factories(Of T As New)  
  •     Public Function CreateT() As T    '必须确保T有默认的构造函数,否则出错  
  •         Return New T  
  •     End Function  
  • End Class  

          类型参数T必须有公共的默认构造函数。若给T没指定构造函数的类型会出错。有了T的默认构造函数后,就可以CreateT创建实例。







4、多个约束

        可以指定类型参数为几个约束,用花括号。

       下面约束:必须是引用类型,且必须有公共的默认构造函数:


[vb] view plain copy
print?


  • Public Class Factories(Of T As {New, Class}) '限制类型参数可以为多种情况(花括号)  
  •     Public Function CreateT() As T  
  •         Return New T  
  •     End Function  
  • End Class  





5、泛型与后期绑定

         泛型的变量与参数在模板代码中被当作Object处理,虽然用约束解决了部分问题、扩展了变量类型,但仍受限制。

         比如,并不知道指定的类型是否支持+-等运算符重载:

[vb] view plain copy
print?


  • Public Function Add(Of T)(ByVal a As T, ByVal b As T) As T  
  •     Return a + b '错误,因不知道是否支持运算符重载  
  • End Function  
  •   
  • '改为下面(option strict off)  
  • Public Function Add1(Of T)(ByVal a As T, ByVal b As T) As T  
  •     Return CObj(a) + CObj(b) '此时应重载+,这样才不会出错  
  • End Function  









五、协变与逆变

        协变逆变利用继承关系 对不同参数类型或返回值类型 的委托或者泛型接口之间做转变。

        协变和逆变是说明父类与子类的相互转换。


         简单地说:子--》父(协变);父--->子(逆变)

                             因为子到父的转换永远正确(协变),而父到子的转换不一定正确所以也称(逆变)


         例如Animal是父类,Dog是从Animal继承的子类。

          如果一个方法要接受Dog参数,那么另一个接受Animal参数的方法肯定也可以接受这个方法的参数,这是Animal向Dog方向的转变是逆变。

          如果一个方法要求的返回值是Animal,那么返回Dog的方法肯定是可以满足其返回值要求的,这是Dog向Animal方向的转变是协变。


         它们的主要应用场合是多态。


1、协变

      子--->父


[vb] view plain copy
print?


  • '父类  
  • Public Class Parent(Of T)  
  •     'add code  
  • End Class  
  •   
  • '子类  
  • Public Class ChildClass(Of T)  
  •     Inherits Parent(Of T)  
  •   
  •     'add code  
  • End Class  
  •   
  • '多态应用中,协变  
  • Public Class CoVariance  
  •     Public Sub MainMethod()  
  •         Dim cc As New ChildClass(Of String)  
  •         Dim dad As Parent(Of String)  
  •   
  •         dad = cc    '子类赋值给父类,协变  
  •     End Sub  
  • End Class  




2、逆变

      父---->子


[vb] view plain copy
print?


  • '父类  
  • Public Class Base  
  •   
  • End Class  
  •   
  • '子类  
  • Public Class Derived  
  •     Inherits Base  
  •   
  • End Class  
  •   
  • '应用(泛型逆变)  
  • Public Class ContraVariance  
  •     '封装一个方法,有一个参数且无返回值,即baseMethod(byval param as Base)  
  •     Private baseMethod As Action(Of Base) = Sub(param As Base)  
  •                                                 'add code  
  •                                             End Sub  
  •     'derivedMethod(byval param as Derived)  
  •     Private derivedMethod As Action(Of Derived) = baseMethod  
  •   
  •     Public Sub MainMethod()  
  •         Dim d As Derived = New Derived()  
  •   
  •         derivedMethod(d)  
  •         baseMethod(d)  
  •     End Sub  
  • End Class  
[url=] 在VB.NET编程中使用数组让您编程有一个质的速度 b2b软件 [/url]





untoVB.NET的字节校验实用的各种方法汇集nextVB.net教您一招可以实现邮件自动发送自动收发邮箱
回复

使用道具 举报

0

主题

605

帖子

589

积分

积分
589
信息发布软件沙发
发表于 2017-5-16 21:17:49 | 只看该作者
,清晰度也很合适。太划算啦

回复 支持 反对

使用道具 举报

0

主题

640

帖子

632

积分

积分
632
推广工具板凳
发表于 2017-5-20 16:17:15 | 只看该作者
,客服很有耐心,我说了很多的要求都一一的帮我改了,有需要还会再来找你们设计的

回复 支持 反对

使用道具 举报

0

主题

641

帖子

627

积分

积分
627
软件定制开发地板
发表于 2017-5-26 01:31:31 | 只看该作者
,而且很时尚,发货也很快,服务态度好,好评!

回复 支持 反对

使用道具 举报

0

主题

2181

帖子

2

积分

积分
2
5#定制软件#
发表于 2017-5-26 14:47:35 | 只看该作者
不错,和卖家描述的一样,值得入手,好评

回复 支持 反对

使用道具 举报

0

主题

595

帖子

559

积分

积分
559
6#定制软件#
发表于 2017-5-31 05:38:45 | 只看该作者
很快,给力卖家赞一个!!!

回复 支持 反对

使用道具 举报

0

主题

627

帖子

625

积分

积分
625
7#定制软件#
发表于 2017-6-10 05:54:46 | 只看该作者
术不错。。。整的巴适。。。

回复 支持 反对

使用道具 举报

0

主题

636

帖子

624

积分

积分
624
8#定制软件#
发表于 2017-6-12 09:30:26 | 只看该作者
模板操作简单方便,店家讲解详细,有详细的安装程序,卖家服务好,有问必答,而且都是第一时间给予协助,解决了很多问题,大家有需要就买这家就对了,很值得信任的卖家!合作非常愉快,下次还来

回复 支持 反对

使用道具 举报

0

主题

1012

帖子

1012

积分

积分
1012
9#定制软件#
发表于 2017-6-14 03:34:40 | 只看该作者
序员哥哥好有耐心!点赞!

回复 支持 反对

使用道具 举报

1

主题

640

帖子

612

积分

积分
612
QQ
10#定制软件#
发表于 2017-6-14 03:50:09 | 只看该作者
路过,支持一下啦

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

相关导读
群发软件AIWROK软件时间方法集合小结
AIWROK软件时间方法集合小结//适用本文档ES5系统安卓 JavaScript引擎Rhinoconst 时间 = { /** * 获取当前时间戳 * @returns {number} 返回当前的时间戳(毫秒) * @example * var timestamp = 时间.当前时间戳(); * printl(timestamp); // 输出类似: 1677649423000 */ 当前时间戳: function() { return Date.now(); }, /** * 格式化时间为指定格式 * @param {Date|number|str
群发软件IOS苹果TabView视图和Horizontal水平布局控件
IOS苹果TabView视图和Horizontal水平布局控件 导航条视图模式可以支持多个页面标签切换案例:创建TAB视图显示视图function show(function fun)参数 func :ui显示以后调用的方法设置tabtab.setTitles(["首页", "关于", "我的"])//关闭视图tab.dismiss()添加子视图tab.addView(tabindex,view)参数tabindex:tab的序号从0开始参数 view:子视图案例Horizontal水平布局控件用于横向放置多个控件案例:
群发软件苹果熟悉layout线性布局和IOS苹果View视图
本帖最后由 群发软件 于 2025-3-27 07:34 编辑 线性布局是垂直或者水平布局类似网格 水平布局 比如就是一行可以放多个控件文本框:按钮:单选框:复选框类似上面这样一行可以放多个控件的就是水平布局垂直布局就是一行只能放一个元素文本框按钮单选复选混合布局,就是水平和垂直嵌套就可以实现复杂的界面例如一个登录界面,先创建一个垂直布局 ,每个垂直布局的每一行再放一个水平布局用户名————————密码————————
群发软件AIWROK软件生成椭圆曲线手势
这段代码定义了一些用于生成和执行贝塞尔曲线手势的函数。具体来说,代码分为以下几个部分: 1随机数生成函数: 这个函数 random(a, b) 使用 rand.randNumber(a, b) 来生成一个在 a 到 b 之间的随机数。不过,在完整的代码中,rand.randNumber 需要是一个已定义的函数或库方法。 2椭圆曲线点生成器: 函数 generateEllipticPoints(a, b, xStart, xEnd, step) 用于根据椭圆曲线的参数 a 和 b,在指定的 x 范围内生成一系列的点。
群发软件AIWROK软件屏幕自动化操作方法汇集
代码的简要说明和一些注意事项: [*]MLKitOcr 文字识别: [*]代码中使用了 MLKitOcr 方法来进行文字识别。'zhs' 和 'zh' 都是中文的识别代码,但通常使用 'zh'。 [*]识别结果通过 getAllString() 方法获取,然后打印出来。 [*]使用完截图后,记得调用 recycle() 方法来释放资源。 [*]截图并压缩: [*]使用 screenShot 方法可以指定截图的尺寸和压缩质量。 [*]检查截图是否成功后再进行后续操作。 [*]计算面
群发软件苹果IOS在IDE中配置AIWork直播插件的详细图文教程
在IDE中配置AIWork直播插件的详细图文教程以下是关于在集成开发环境(IDE)中配置AIWork直播插件的详细步骤说明,帮助您顺利完成设置。第一步:安装IDE1. 下载并安装IDE· 下载安装包:访问官方网站或可信来源下载最新版本的IDE安装包。· 安装步骤:a. 双击安装包文件,按照提示完成安装。b. 安装完成后,重启计算机以确保环境变量生效。· 验证安装:打开IDE,检查是否能正常运行,确保所有组
群发软件AIwok软件苹果IOS手机初始化设置和IOS HTTP接口
配置要求:IDE AIWORK >3.25手机 >= iphone6sIOS版本 >=IOS15(ios15不支持画中画日志,16以上支持)苹果HID硬件必须设置:自动息屏:必须关闭,不然截屏权限会自动关闭蓝牙:必须打开辅助触控:必须打开 (设置->辅助功能->触控->辅助触控->打开)软件安装1.下载tf并安装https://testflight.apple.com/join/1sVURYPb或者扫二维码下载 安装完tf以后 再安装aiwork初始化第一步 硬件连接手机,选择硬件第二步 开启辅助触
群发软件AIWROK软件多线程协作示例代码解析
AIWROK软件多线程协作示例代码解析 详细说明 [*]线程对象创建 [*]使用new thread()创建两个独立线程对象 [*]dataThread用于数据处理,logThread用于日志记录 [*]每个线程有独立的执行上下文和生命周期 [*]数据生成线程 [*]通过runJsCode方法执行匿名函数 [*]使用for循环生成1-5的序列数据 [*]java.lang.Thread.sleep(1000)实现1秒间隔(Rhino引擎特性) [*]线程命名为"数据线程"便于调试识别 [*]日志记录线程
群发软件AiWork软件下载蓝奏云OCR文件到文件夹
这段代码是一个用于从蓝奏云(Lanzou)下载文件的自动化工具脚本,主要基于JavaScript编写,并且是在一个安卓自动化环境中运行的,例如使用AiWork这样的自动化IDE。代码中定义了一个主要的函数downloadLanzouFile,它接受三个参数:文件的URL地址url,保存文件的路径saveFilePath,以及最大重试次数maxRetries(如果未提供,函数默认设置为5次)。代码的主要功能和步骤如下: [*]初始化和配置: [*]定义了蓝奏云的备用域
群发软件setTimeout__方法异步延迟加载函数
这段代码定义了一个简单的任务链,模拟了一个从数据查询到数据处理再到数据保存的流程。代码中使用了runTime.setTimeout来模拟每个任务的执行耗时。以下是代码的详细说明: [*]taskOne函数:这是第一个任务,负责开始数据查询。 [*]使用printl函数打印一条消息,表示任务一即将开始。 [*]使用runTime.setTimeout函数来模拟数据查询的过程,设置的延迟时间为3秒(3000毫秒)。 [*]在3秒后,生成一个模拟数据字符串"查
群发软件floatUI悬浮窗 实用示例合集
floatUI悬浮窗 实用示例合集如何使用 floatUI 创建不同的 UI 组件,并为它们设置点击事件。每个示例都展示了不同的 UI 布局和事件处理逻辑。示例 1: 创建一个带有多个按钮的垂直布局,并为每个按钮设置不同的点击事件var f1 = new floatUI(); f1.loadSXML(` <vertical> <button text="按钮1" id="button1"/> <button text="按钮2" id="button2"/> <button text="按钮3"
群发软件AIWROK软件找图__方法小汇集
方法一:定义图像查找函数 [*]功能:在指定的查找区域内查找与模板图像相似度达到设定值的目标,并自动点击该目标的中心位置。 [*]参数: [*]searchRegion:查找区域的相对坐标,格式为 [x1, y1, x2, y2],其中 (x1, y1) 是左上角坐标,(x2, y2) 是右下角坐标。 [*]templateImage:模板图像的Base64编码字符串。 [*]similarity:相似度阈值,用于判断是否匹配。 [*]流程: [*]获取屏幕截图并转换为Mat格
群发软件awirok软件找色__方法小汇集
群发软件AIWORK 软件全功能 OCR 查找区域功能代码示例
    // 第一个示例:获取屏幕截图并进行 OCR 文字识别(简体中文)var img1 = screen.screenShotFull();var ocr1 = img1.MLKitOcr('zhs');var text1 = ocr1.getAllString();printl(text1);img1.recycle();/*说明:- 这是一个最基本的 OCR 示例。- 使用 MLKitOcr 方法通过简体中文词库识别截图中的文字。- 最终输出识别到的全文本信息。*/// 第二个示例:指定区域内的 OCR 文字识别(中文)var img2 = screen.s
群发软件AiWROK软件里的OpenCV图片分辨率压缩和质量压缩
// 导入必要的Android和OpenCV类importClass(android.graphics.Bitmap);importClass(java.io.File);importClass(org.opencv.core.Core);importClass(org.opencv.core.Mat);importClass(org.opencv.core.Size);importClass(org.opencv.imgproc.Imgproc);// 全屏截图var img = screen.screenShotFull();if (img.isNull()) {printl("截图失败");exit();}// 原始图片信息var originalPath = "/sdcard/original.jpg";img.save(originalP
群发软件定时任务示例:使用 setInterval 和 clearInterval 实现多种功能
1. 倒计时功能var countdownTime = 10; var countdownInterval; function updateCountdown() { if (countdownTime > 0) { console.log("剩余时间: " + countdownTime + "秒"); countdownTime--; } else { clearInterval(countdownInterval); console.log("倒计时结束!"); } }用法启动:startCountdown()停止:stopCountdown()应用场景游戏倒计时、会议提醒、考试计时、烹饪计时等。2. 实时时
群发软件AIWORK软件将数组↔互转字符串
AIWORK软件将数组↔互转字符串1.方法将数组转换为字符串// 定义函数function myFunction() {// 定义一个包含水果名称的数组var fruits = ["Banana", "Orange", "Apple", "Mango"];console.log("原始数组: ", fruits);// 使用 toString 方法将数组转换为字符串var str = fruits.toString();console.log("转换后的字符串: ", str);// 返回转换后的字符串return str;}// 调用函数var result = myFunction();2. 将数组互转字符串/
群发软件Boolean对象构造AIWROK函数深度解析
本类目代码集合:  //第一个,boolean.constructor_函数的引用 // 创建布尔对象 var myBool = new Boolean(true); // 访问构造函数 printl(myBool.constructor); // 输出: function Boolean() { [native code] } // 确认构造函数的类型 printl(myBool.constructor === Boolean); // 输出: true //第二个,boolean.toString___布尔转字符 // 创建一个 Boolean 对象 var boolTrue = new Boolean(true); v
群发软件AIWROK软件随机时间和随机倒计时用法技巧分享
群发软件安卓自动化[auto]大集合第一部
安卓自动化[auto]大集合第一部第一个:back按下回退键auto.back();这个代码示例展示了如何调用一个名为 back() 的函数来返回上一页或执行某种“返回”操作。例子:function demoExample() { // 打印信息表明即将返回上一页 printl("即将返回上一页"); // 使用 auto.back() 返回上一页 auto.back(); } // 调用示例函数 demoExample(); 代码说明:function demoExample() { ... }:定义了一个名
群发软件AIWROK软件随机位置范围点击和范围随机拖动
   /* * 随机位置点击函数 * @param {number} x - 点击位置的百分比 X 坐标 * @param {number} y - 点击位置的百分比 Y 坐标 * @param {number} x范围 - X 坐标的随机范围 * @param {number} y范围 - Y 坐标的随机范围 */ function 随机位置点击(x, y, x范围, y范围) { // 将百分比坐标转成真实坐标 var x1 = screen.percentToWidth(x); var y1 = screen.percentToHeight(y); /
群发软件AIWORK软件FTP完整例子自动链接可以上传可以下载
AIWORK软件FTP完整例子自动链接可以上传可以下载/* 欢迎使用AiWork安卓自动化IDE 帮助文档: http://help.autoapp.net.cn 官方地址: www.aiwork24.com qq群: 743723025 */ // 加载FTP库 // 通过rhino.loadDex方法加载名为"ftp.dex"的Java库文件,该文件包含了用于FTP操作的类 rhino.loadDex(project.getResourcesPath() + "ftp.dex"); // 导入所需的FTP操作类和Java IO包 importClass(org.apache.common
群发软件AWIROK软件:如何实现OCR找字并点击功能?
var img = screen.screenShotFull(); var ocrres = img.paddleOCR(640, [0, 0, 1, 1]); var dect = ocrres.findIncludeText('今日头条'); if (dect != null) { console.log('今日头条'); dect.click(); // 点击检测到的“今日头条”区域 dect.hidClick(); sleep.millisecond(3000); // 暂停3秒 } else { // 找图返回目标数组 var detects = opencv.findImagesEx('图色982357继续安装.cv');
群发软件手机改了分辨率后有误差用公式计算加减还原点击
有的人用改分辩率软件,更改了手机的分辩率,为了让所有手机通用一种点击方法,计算偏差,可以用这段代码实现。两种方法如下:第一种方法:function calculateFunction(inputValue) { function leastSquaresFit(x, y) { var n = x.length; var sumX = 0; var sumY = 0; var sumXY = 0; var sumX2 = 0; for (var i = 0; i < n; i++) { sumX += x;
群发软件原生webview的h5如何跟aiwork交互
原生webview的h5如何跟aiwork交互 原生activity和h5交互案例.zip void runJs(function code)h5执行app JS脚本window.at.runJs(function (){ //这里写ATjs代码 printl("你好"); auto.home();}.toString());void runJsFile(String file) H5运行APP JS文件window.at.runJsFile('主脚本.js');void callFunction(String funname,String arg) H5执行脚本方法window.at.callFun('main',"hello");Str
群发软件AIWORK软件图片二值化封装使用方法说明
群711841924// 引入 Android 和 OpenCV 的类 importPackage(org.opencv.core); importPackage(org.opencv.imgproc); importPackage(org.opencv.android); importClass(android.graphics.Bitmap); function screenshotAndBinarize(width, height, quality, threshold1, threshold2) { // 进行屏幕截图 var bitmap = screen.screenShot(width, height, quality).getBitmap(); // 将 Bitmap 转换为 OpenCV
群发软件使用AIWORK的ADB命令执行: 实现安卓设备的远程命令
第一个例子:开启代理模式判断agent.start()agent.start() 函数用于开启代理模式,需 root 权限,无需参数。此函数执行后会返回一个布尔值:如果成功返回 true,否则返回 false。下面是一个可能的使用例子: // 尝试启动代理模式 let result =agent.start(); printl(result); if (result) { console.log("代理启动成功!"); } else { console.log("代理启动失败,请检查是否具有root权限。"); } 此
群发软件理解Activity:安卓应用中的关键组件
在安卓开发中,Activity 是一个非常重要的组件,主要用于以下几个方面:用户界面展示:每个 Activity 通常代表一个完整的屏幕或界面,用户与应用的交互主要通过 Activity 实现。例如,一个邮件应用可能包含一个显示邮件列表的 Activity,以及另一个用于阅读邮件内容的 Activity。生命周期管理:Activity 有一个生命周期,即创建、启动、恢复、暂停、停止和销毁等状态。开发者可以通过重写
群发软件AIWORK全能图像处理开发指南:从截图采集到OCR识别的全链路实现
1.截取屏幕的全屏截图:var img = screen.screenShotFull(); 这行代码用于截取当前屏幕的全屏截图,并将截图存储在变量img中。2.文字识别,默认语言为中文:var ocr = img.MLKitOcr('zh'); printl(ocr.getJsonString()); 使用MLKitOcr方法对截图img进行文字识别,指定语言为中文’zh’,并将识别结果以JSON字符串形式打印出来。3.获取图片大小(以字节为单位):var size = img.byteSize(); printl('图片大小: ' + size + ' 字
群发软件AIWROK软件中的okHttp上传文件详解
以这个网站为例子https://ocr.wdku.net/我们首先抓包上传的参数通过以上抓包我们分析出 几个关键点第一:上传的url是 https://ocr.wdku.net/upload第二:二进制的参数名字是 file第三:其他参数user,name,from,fileName现在使用okhttp上传方法以此填写参数var http1=new okHttp(); var fromdata= new map()//其他参数使用map格式 fromdata.add("user","default") fromdata.add("name","t019bf9f2ac19af88b0.webp.png_173915
群发软件通过HTTP接口实现屏幕连续点击功能的易语言代码示例
.版本 2 .支持库 eHTTP .程序集 窗口程序集_启动窗口 .子程序 _启动窗口_创建完毕 .子程序 发送HTTP请求 .参数 请求URL, 文本型 .局部变量 响应内容, 文本型 // 创建HTTP请求对象 HTTP请求对象 = HTTP请求 () // 设置请求URL HTTP请求对象.设置URL (请求URL) // 发送GET请求 响应内容 = HTTP请求对象.发送GET () // 显示响应内容(可选) 信息框 (响应内容, #信息图标, “响应内容”) .子程序
群发软件实现AIWork软件开机自动启动且不弹出界面
这个代码的主要作用是,手机一开机就自动不弹界面,自动开始运行脚本,如果你想定时脚本,也是需要先打开脚本的,这个需要自己在主脚本的JS运行才可以// 自启动逻辑if (autoStar == true) { printl("开机自启动"); Import("主脚本.js");} else { // 加载主界面 var win = window.loadUI("主界面.ui"); win.show();}这段代码主要用于设置一个应用程序在开机时是否自动启动。代码逻辑如下: [*]代码首先检查变量 autoS
群发软件AIWORK+图鉴:点选验证码智能识别系统集成指南
详细版:function sendImageToAPI(username, password, typeid) { var url = "http://api.ttshitu.com/predict"; // API地址 // 截取全屏图像并裁剪验证码区域 var img = screen.screenShotFull().cutImagePercent(0.17, 0.412, 0.83, 0.57).toBase64(); // 准备POST请求的数据 var postData = JSON.stringify({ username: username, password: password, typeid: t
群发软件MuMu 模拟器借助 ADB 桥接与 AIWROK 软件成功连接的步骤详解
MuMu模拟器桥接ADB模式连接AIWROK软件教程:他模拟器官方网站:https://mumu.163.com/ 第一步准备工作, 同时开多个模拟器会导致端口冲突,新手先折腾一个,成功后再试多开。 如果之前开过其他模拟器(雷电、夜神等),先全部关掉!先确定你这里只有一个模拟器,因为多个,他可能端口不同的,一个连接上了,其它也能链接上,最好是先一个先折腾着,这样后面就简单了。 然后开启他的网络桥接状态。打开MuMu模拟器 → 点击右上角
群发软件JavaScript中贝塞尔曲线的实现与应用
随机数生成函数 function random(a, b) { return rand.randNumber(a, b); } /** * @param time_ms {number} 执行时间 ms 例如 3000 * @param t {number} 间隔系数 0-1 间, 越小线条线条越圆润,计算量越大, 例如 0.005 * @param pt {number[][]} 控制点坐标的二维数组 例如 [[137,169],[140,283]] */ function bezier(time_ms, t, pt) { var gesture1 = new path(); // 创建一个手势对象 gesture1.se
群发软件键鼠.随机百分比点击方法结合屏幕百分比和随机偏移,实现精准且自然的
第一个,键鼠HID随机点击例子const 键鼠 = {}; 键鼠.点击 = function (x, y) { if (typeof x === "undefined") return false; if (typeof y === "undefined") return false; return hid.click(x, y); } 键鼠.随机点击 = function (x, y, random) { if (typeof x === "undefined") return false; if (typeof y === "undefined") return false; let random_s = random || 10; let x
群发软件应用关闭函数的设计
第一个:定义一个关闭当前窗口的函数// 定义一个关闭当前窗口的函数 function close() { // 本示例创建一个带有一个按钮的窗口,点击按钮关闭当前窗口 // 初始化一个新的活动(窗口) var ac = new activity(); // 加载布局代码,使用 LinearLayout 替换 vertical ac.loadXML(` <LinearLayout> <Button id="button1" text="第一个按钮"/> </LinearLayout>
群发软件多点屏幕颜色检测:10秒内变化监控
群发软件智能链接:在安卓上无缝切换快手与抖音
1.这是一段快手的意图跳转例子// 导入包 importClass(Packages.android.content.Intent); importClass(Packages.android.net.Uri); importClass(Packages.android.content.ActivityNotFoundException); importClass(Packages.android.widget.Toast); importClass(Packages.android.os.Handler); importClass(Packages.android.os.Looper); // 设置快手用户页面的URL var userId = "2037335125"; var url = "kwai://prof
群发软件在AIWROK软件中使用OkHttp设置HTTP请求头中的Cookie并输出
群发软件监听广播事件:onBroadcastEvent 方法详解
本帖最后由 群发软件 于 2025-1-16 09:43 编辑 event事件侦听使用 onBroadcastEvent 方法的示例:// 监听广播事件 event.onBroadcastEvent(function(msg) { // 在接收到消息时打印出来 print(msg); }); 说明:onBroadcastEvent 是一个用于监听广播事件的方法。它接收一个函数作为参数,该函数会在事件触发时执行。在这个例子中,当收到消息时,打印该消息。这个示例演示了如何实现一个简单的事件监听
群发软件自动下载与安装:多线程管理指定文件夹APK和图片文件的下载完整性检查
自动下载与安装:多线程管理指定文件夹APK和图片文件的下载完整性检查
群发软件用AiWork如何写出一个一个播放器呢?
用AiWork如何写出一个一个播放器呢? 用软件可以写出一个简易的播放器,专门听歌甚至占用内存极少,极度容易的播放器例子。 传到手机只需要播放就可以了。这个如果您希望从一个MP3列表中逐个播放文件, 您可以先创建一个包含所有MP3文件路径的数组, 然后使用循环或递归的方式来遍历并播放这些文件。这里是一个示例代码,展示了如何实现这一功能: 这段代码首先定义了一个mp3List数组, 包含了您想要播放的M
群发软件蓝奏云-文件下载(2.8.9版本)
群发软件自动留言工具下载
自动留言工具下载,这个软件可以自动评论这四个网站,也是新加新收集回来的,不过这些网站虽然可以匿名评论留言,放网址,放宣传的关键字,但却有一个验证码,这个验证码吧,你整起来是可以识别的,但没有必要,还不如自己对接火眼这些打码网站来的实在,现在人工智能也可以识别验证码了,而且准确率比普通的打码网站更高,甚至可以给出更好的图片修复技术,也算是一个人工智能的一个彻底应用层级吧,有可能 GPT5 后面连视频验证码
群发软件自动网址转换自动提交蜘蛛池软件
自动网址转换自动提交蜘蛛池软件,增加二个标题作为宣传目标的网站,它们可以自动的增加标题作为关键字和宣传联系方式,然后通过微信读书和微软的这个软件搜获功能,将网址转换成宣传链接的地方的,目前这两个网址是有效的,收录快,后面也做了一个蜘蛛池的扔投喂,也就是发着发着,他会自动的去发一个所有网址,然后清空所有网址,每次只有两个作为提交的作用,能达到发外链,投哺蜘蛛池的效果的,也就是这二个现在有效果的,提交
群发软件自动评论网站全自动发帖软件
自动评论网站全自动发帖软件,这个软件增加七个可以自动评论的网站,效果还蛮好的,他们都是相似后台的,有几个还是极高权重的留言网站,打开网址,可能不是直接的发帖顶帖的输入框,但是只要加一个点击发言就可以进去评论了,网站自由度比较高,可以发自己的标题和内容,也可以发一些外链上去,收录都极高,都不用发帖都可以有很高的权重网站,都是这些实际的网址才行,有的同一个网站,收录不一定好,但有的帖子浏览量高,发帖权
群发软件2025新版本自动评论自动提交蜘蛛池软件
自动评论自动提交蜘蛛池软件,今天因为网站过时,更新三个更加时效的网站,他们都可以自动的在收录比较好的帖子增加收录,你可以在这里刷广告,也可以在这些地方刷外链,都可能被秒收录的节奏,这些评论,往往都是他们自己刷了几千万条的外链,刷了几千万条的广告信息留下的繁殖链接区域名,网站收录好才是真的亮眼的地方,打卡一下就可以收录,不记录权重,只看最终的百度收录效果吧,这些网站是实时放一些收录的热门帖子评论效果
群发软件精英乓乒网全自动发布帖子软件下载
精英乓乒网自动发帖软件,这个网站客以久了,居然还可以发帖,吸引来了一群人盯在它的网站进行发帖子,不过现在不论是买号发还是什么号,都给安排上了二个验证码,登陆一个会动的验证,好在登陆成功一次后,后面不用,不过他的发帖一个是回答问题的验证码,一个是会动的验证码,会动的验证码识别率不是很高的,毕境他有时候会截图和会动的那一秒时候进行了切换图片,这样就可能导致截图不成功,这么久了,所有平台对这些会动的验证
群发软件百度贴吧全自动群发软件下载
百度贴吧软件,这个网站发帖是比较难的,但效率可以说全网最高的,所以总是有一种日不落的帝国感觉,三到二头,都会有人拉出来软件跑一跑,这个网站也是蛮折腾的,有时候严格,有时候松驰,导致有的人专靠这个吃饭的,总是有一种吃不到葡萄说葡萄酸的感觉,这个脚本用 POST 把图片上传上去,然后按照自己需要,弄成了图片成文字组合,很明显的软文结构,能上去一遍不被收录也无所谓,一样人气满满的在上面生根发了芽,有委大的人气
群发软件策梅特博客自动发帖工具下载
策梅特博客群发软件,这类博客网站可以用最简单的代码实现自己的博客需求,以前是先流行的,现在只能被当作新手的训练场了,这种博客需要自己购买登陆账号才可以发的,只有一个登陆,一个发帖界面,首页是实时更新的,发什么就实时更新什么,这类网站都有新手保护期,即你前期发什么都容易收录,后面就没有可以发展的条件了,网站发帖快,没有什么阻碍的地方,收录也是实时提交的,他们都开通了后台对接的,所以发帖收录不用另外提
群发软件apipost博客群发软件
apipost博客群发软件,这个网站是 POST 发博客的地方,注册账号要邮箱验证码,注册后想发博客还要手机验证码的,绑定一次后就可以发帖,发帖的时候有一个按住验证码,刚好软件也有这个功能,按住五秒就可以实现过这个验证码的样子,没有啥难度,就是账号可能比较麻烦一些了,软件可以自动登陆账号,然后打开发博文的网页,再按住验证码识别成功后,输入标题内容,群发博客的任务就这样完成了,这个软件可以自动切换账号去发帖,发
群发软件aliexpress产品网站发布宣传软件
aliexpress产品发布软件,这个是外贸产品供应信息发布网站,对于国外的 B2B 网站可能还在发展阶段的,所以网站对于这些还是比较吃香的,aliexpress.com 这个网站是一种分类比较强大的网站了,他们国外的,还是比较注重细节分类的,所以会有很多地方需要调试,不过网站也提供了一 键复制属性的功能,和以前机械网站一样,因为他们分类那种细节都到了螺丝纹度的,如果用属性复制功能,会比较简单,只要改一改标题,图片,和视频就可
群发软件51搜了网发布宣传软件全自动发布帖子软件下载
搜了网资讯产品自动发布软件下载, 这个软件可以自动发产品,产品这里是发家电维修类别的,比较复杂一些有几十个选项要填的,第一次做这个网站,你会感觉到头皮发麻,不知所措,很多下拉什么的都要逐个调试,图片这里还要上传六张图片,不然会出错,发不出去的,第二个选择发帖项是资讯的,以前有验证码,现在全部可以不用验证码自动发帖子,轻轻松松就可以发完导入的所有内容帖子,再也不用填那个计算的验证码了吧,网站收录还是
群发软件抖音图文和视频发布工具下载地址
抖音图文发布和抖音视频自动上传软件,这个软件可以自动上传抖音图片并且附上文字和获取图片的各种各样名称作为标题进行发布,有的人账号似乎拖动不了网页,只好出这个座标点击的版本,这样就不会有啥问题了,他是可以准确定位到上传按钮,并且准确的输入内容作为标签,这样就可以发上去的内容标题带上标签关键字,带上账号切换功能,妥妥的是一个宣传视器,用这个软件发布的视频和图文,基本不会被封号,只要你发的不是太快,发的
群发软件发布宣传软件自动评论留言软件
增加四个评论网站发信息,这里三个网站是一样的,另一个网站比较特别,是一个下载站的评论,还是极少有网站有这么自由的,不过正因为他们秒发秒收录的极致才会被看中选择,一个是鞋袜网站,一个叫懒人计算器网站,一个叫生活养生 70 条,还有一个叫微导航网站,这个网站没有验证码的,全部自由发挥,只要秒发秒显示的,不用审核,另外三个网站也是有三条链接收录比较好,其它自创的收录是不行的,他这些留言网站,只针对收录好的某
群发软件易次元图片发布头条软件
易次元图片发布头条软件,这个网站可以说是动漫不变的话题,他们总是会创作出各种各样的人气话题,所以这个网站收录一直是一个重点关注对象,只是这个网站也是确实管的极度严格的,不管你是在里面创建小组,还是去增加图片相册,或是直接发帖,都有可能被百度收录,这个网站一个号只能发五帖,就自动切换账号了,不过要是出验证码就没有好的法子了,他这个验证码,拖对了也会经常判断你是错的,所以滑动方法是没有问题的,只是人也
群发软件OOKT百科网站发布宣传软件
OOKT百科网站自动发布软件,这种头条新类网站就是以前的 ZBLOG 的模块,这类网站搭建容易,也比较安全,没有什么大的漏洞,主要是简单稳定,只要服务器还可以,几乎不会出什么差错,这个网站也是养熟了,然后出来放号出售的,这类网站做好了后,收录几乎都不会差到哪去,都比较好的百度收录效果,买好账号添加到软件的账号密码列表,导入标题内容自动发帖,这个网站的分类会比较麻烦一些,主要是他这个嵌套的操作代在码有一点编差
群发软件星空社区全自动B2B发帖软件
星空社区全自动B2B发帖软件,这个网站是 B2B 后台的样子,做了二套网站,一个是针对普通网页版本进行发帖的,一套是 POST 后台发帖的形式,这样就可以自动的拥有二种模式,一个是发的快,一种是收录好,有的时候你就像是在这些地方做有用功似的,你把能量传递过去就会得到两种效果,看你怎么选择,有蜘蛛池的时候,当然是用自己的 POST 版本了,要是没有就用普通的版本浪费点电能,一定要传二张以上的图片,图片不要超过 3M 比较好
群发软件鸡病专业网论坛全自动发帖软件
鸡病专业网论坛全自动发帖软件,这是一个发外链的论坛哈,你要把链接放到软件列表的内容 2 和内容 3 已经加上了白底了,正常内容可以放在内容 1 这样就可以做到悄悄进村,打枪的不要了,这个软件是先采集整个版块的网址,放到列表中去,每一次都会有一个大循环,重复操作,为什么要这样弄呢,因为这个脚本只是顶帖用的,没有什么大的效果操作,顶的太快被发现了可能就是一顿乱封号处理了,论坛有点被全部扒下来顶的感觉,发链接不
群发软件gongkong网早自动论坛顶帖软件
gongkong网早自动论坛顶帖软件,现在发帖太多限制了,很多人把目光转到这些大论坛,进行了偷偷发外链,怎么个方法,其实要是你查到了这些人的外链就很明白是怎么弄的,就是把自己的网址,弄成白底颜色这样操作,这样管理员是看不到你发了网址一堆的在下面的,加上现在人都很少有查询的,只要不是很过份,基本都可以发很久,就像现在这个论坛一样,看了很多人都在偷偷的发一些蜘蛛链接在里面,这样就可以造成迷糊的操作了,这个软件
群发软件盐城商务网全自动发布帖子软件
盐城商务网全自动群发软件,这个网站是 B2B 网站来的,买号才可以每天发几百条,要是加上现在的蜘蛛池技术,收录还是很可观的,要是没有蜘蛛池就会收录的极少了,这个软件包有二个功能,一个是 POST 的后台发送,能全自动看不到过程,只有过程日志呈现,另一个是普通的版本,能看到运行过程,第一个脚本是占用资源是比较少的,另一个显示过程的肯定就加载的东西自然就多,网站有五个分类可以发,全部都导入到软件里去了,你只要操
群发软件自动网站评论软件下载地址
后台评论更新五个网站打包,这几个网站只有一个后台是不同的,其余的都是帝国的 CMS 系统,后台和验证码都一样的,网站的验证码都几乎一样,可以用图鉴这个网站打码比较便宜一些,都不需要注册账号,匿名就可以评论,他显示的是 IP 进行的,验证码也可能会打错,不管这个只好按出错率判断了,五个网站,第一个要不肜填写标题,其余几个都要填写标题,标题带联系方式就行了,后面的这四个网站可以填写内容,他们主要不是收录当页,
群发软件扬中头条自动发布软件
扬中头条自动发布软件,这个网站做提极度粗糙的,连网站原来的 LOGO 都没有换掉,可是你更气的是,他收录居然出奇的好,你这能找谁说理去,不过网站他主站是比较多有价值的东东的,可发帖自然也有一个原始的验证码了,导入账号可以换号的,软件都已经做进去了,好在激活不用这么麻烦,注册一会就可以发帖,本来做了全自动发帖的过程,但注册还是有失败率,因为这个验证码也不是百分百过,要是自己写逻辑自己用的还是可以的,不过要
群发软件阴山论坛网站群发软件
阴山论坛网站群发软件,这个网站是论坛来的,改了很多地方,基本你找不到哪里发帖,哪里回帖子,网站图片也乱七八糟的,不过也没有关系了,反正能收录很多就行了,网站注册账号是免费的,注册一个账号要二分钟后才可以发帖,只要注册的号导入进去软件的 ID 列表,就可以全自动切换账号发帖,完全不用理,导入标题内容会自动切换的,没有什么需要手工操作的,不过发帖有一个验证码,需要自己充好火眼这些接口,也是会自动打验证码的

QQ|( 京ICP备09078825号 )

本网站信息发布软件,是可以发布论坛,发送信息到各大博客,各大b2b软件自动发布,好不夸张的说:只要手工能发在电脑打开IE能发的网站,用这个宣传软件就可以仿制动作,进行推送发到您想发送的B2B网站或是信息发布平台上,不管是后台,还是前台,都可以进行最方便的广告发布,这个广告发布软件,可以按月购买,还可以试用软件,对网站的验证码也可以完全自动对信息发布,让客户自动找上门,使企业轻松实现b2b发布,这个信息发布软件,均是本站原创正版开发,拥有正版的血统,想要新功能,欢迎提意见给我,一好的分类信息群发软件在手,舍我其谁。QQ896757558

GMT+8, 2025-4-1 06:11 , Processed in 0.441789 second(s), 57 queries .

宣传软件--信息发布软件--b2b软件广告发布软件

快速回复 返回顶部 返回列表