精华内容
下载资源
问答
  • VB 删除数组中指定元素实例

    热门讨论 2010-06-07 14:13:35
    VB 删除数组中指定元素实例 VB 删除数组中指定元素实例
  • VB中,动态数组输入数据

    千次阅读 2019-06-10 23:14:06
    Private Sub Command1_Click() Text1.Text = “” Dim s As Long, i As Long ...a(s) = InputBox(“请输入字符串,输入空串时结束”, “输入”) s = s + 1 Loop Until a(s - 1) = “” For i = 0 To s - 2 Text1...

    Private Sub Command1_Click()
    Text1.Text = “”
    Dim s As Long, i As Long
    Dim a()
    Do
    ReDim Preserve a(s)
    a(s) = InputBox(“请输入字符串,输入空串时结束”, “输入”)
    s = s + 1
    Loop Until a(s - 1) = “”
    For i = 0 To s - 2
    Text1.Text = Text1.Text & “第” & CStr(i + 1) & “个是:” & CStr(a(i)) & “”
    Next i
    Erase a
    End Sub

    在这里插入图片描述

    展开全文
  • VB数组求平均成绩

    2010-06-07 14:19:52
    VB数组求平均成绩 VB数组求平均成绩
  • VB-数组、集合、泛型

    2019-06-24 16:09:59
    变量、数组、集合、泛型的发展 最开始用内存中一个位置映射一个值,用变量来“使用”这个值。 进一步发展,用变量来引用一组值,这就是数组。由数组概念,发展出链表、堆、栈,进行排序、检索等。 但这并不能完全...

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

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

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

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

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

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

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

    一、数组

    1、数组的定义      

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

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

             数组的定义:

            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

    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、不定数组

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

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

           

           未处理,其值为空。

            ReDim

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

    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只能修改最后一维的大小。

        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) 作为有效值并且允许重复的元素。

    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进行排序,所以最后不需排序,就可得到排序的结果:

                 

    4、Queue 队列

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

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

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

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

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

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

              

    5、Stack 栈

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

              

             注意:比较与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)  

            '不需要装箱,都是值类型
            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是点位符类似于参数。它表示 必须提供一个用来定制泛型

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

            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。也就是说

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

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

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

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

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

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

    3、Nullabel   可空类型

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

            Nullable不是值类型。

            Dim intValue1 As New Nullable(Of Integer) '可为空的Integer类型
            Dim intValue2 As Integer?   '与上句等效

            intValue1 = 3
            intValue1 = Nothing '可为空,正确
            intValue2 = Nothing
             

            Dim intValue1 As New Nullable(Of Integer) '可为空的Integer类型

            intValue1 = Nothing
            If intValue1.HasValue Then '判断是滞有值
                MessageBox.Show("有值")
            Else
                MessageBox.Show("空值")
            End If
                  在取得这样的类型时,当用判断来说明值的情况。

    4、泛型类型

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

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

         (1)泛型的基本用法

            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。


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

        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

                可以这样调用上面函数:
        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

              泛型还可以作为传参:
        Private Sub useGeneric(ByVal k As Generic.Dictionary(Of Integer, String)) '泛型作参数
            'add code
        End Sub

             (2)继承

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

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

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

    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)

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

                


    5、泛型方法

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

            

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

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

               下面重载泛型方法:

    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)泛型类

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

    '创建泛型类(定义)
    Public Class SingleLinkedList(Of T) 'T可自定,但在使用中,声明时须指定明确的类型
        'add code
    End Class
               上面在使用(声明)中,就须指明T的具体类型,T与变量命名方式一样。

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

    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完善链表类:        

    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

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

        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
             运行,结果如下:
               

         (2)泛型类的其它功能

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

    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)类、泛型类与继承

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

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

    '泛型继承现成的类
    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)结构、接口中使用泛型

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

    '结构中使用泛型 
    Public Structure MyCool(Of T)
        Public value As T
    End Structure
                 这样,在使用时就可以:   Dim  data  as MyCool(Of   Guid)

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

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

    '接口使用泛型
    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):

    '模块中使用泛型
    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的属性和方法:

    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


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

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

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

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

    '约束类型参数必须是某类的子类(下例为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、类、结构的约束

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

    '约束(限制)类型参数是引用类型
    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约束,来确保该类型有默认的公共构造函数。

    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、多个约束

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

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

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


    5、泛型与后期绑定

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

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

    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、协变

          子--->父

    '父类
    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
    --------------------- 
    作者:dzweather 
    来源:CSDN 
    原文:https://blog.csdn.net/dzweather/article/details/10948857 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • VB学习记录——数组

    万次阅读 多人点赞 2019-07-06 13:05:49
    数组知识初步总结 1.定义一个数组,其实就是让系统在内存中分配一个连续的区域,用来存储数组的元素。其格式为:Dim 数组名字 (下界 To 上界) As 类型。 Dim MarkVB(1 To 30) As Integer '定义一个一维数组 上界...

    数组知识初步总结

    1.定义一个数组,其实就是让系统在内存中分配一个连续的区域,用来存储数组的元素。其格式为:Dim 数组名字  (下界 To 上界) As  类型。

    Dim MarkVB(1 To 30) As Integer '定义一个一维数组  上界30  下界是1  共30个元素。 也可以Dim MarkVB(29) As integer,此定义下表从0开始,元素也是30个。   加上Option Base 1  ,Dim MarkVB(30) As integer这个语句也是30个元素,下标从1开始。数组大小=上界-下界+1。

    2.动态数组 ,不能定义数组的维数和个数。Dim  Mark()  As Integer  使用的时候重新声明     redim Mark(n)即可。使用关键字Pereserve可以保存之前的数组内容。

    3. ReDim 语句的下标可以是常量,也可以是有确定值的变量,程序书写时可以多次使用ReDim来改变数组的大小,但是每次使用Redim语句都会造成数组之前数据的丢失,使用Preserve选项对数组进行重新说明时,将会保留数组中原来的数据,但是该参数只能改变最后一维的大小。

    4.数组输入函数 Array(),此函数只能对一维数组进行赋初值,并且这个数组必须为Variant变体型,不能声明数组的大小和类型。Dim  Mark() ,Mark=Array(1,2,3)  ,此时可以利用Ubound()函数确定数组的上界,比如Ubound(Mark)=2,利用For循环可以输出数组元素。

    5.Val()是一个类型转换函数 ,可以把字符串转换成相应的整数,Val("-3")=-3   VAL("vb5.0")=0  VAL("12 bC")=12  VAL与CSTR功能相反,CSTR将数值表达式的值换成字符串        CSTR(125)="125"

    6. 选择法排序

    思想:求取数组最值下标,并交换位置。

    步骤: 1. 每一轮在未排序的数组中,找出最值和第一个元素进行交换,这样就确定了一个元素的位置

                 2. 未排序的数组范围缩小一个,继续采取上述步骤进行新的排序

    注意一下  n个数据只要进行N-1轮排序即可  附上一个代码

     7.冒泡法排序

    思想:冒泡排序 每一次将相邻的两个数字进行比较,比如10个数字。每一次比较相邻的两个,让比较大的数值往下走,第一轮比较9次就可以将最大的数字排到最后面,10个数字需要进行9趟比较,第i趟比较的次数为10-i.

    注意点:冒泡排序是可以提前结束的,如果在某一趟的排序比较中,没有发现变量的下沉,那么说明数字已经是有序排列,则此时可以终结排序。设置一个标志变量 ,放在内循环中,用来检测排序是否完成 。程序如下

    8. 插入数据,在有序数组中插入一个数据

    基本思想:首先寻找插入的位置,其次将插入位置之后的元素一次向后移位 。  

    注意事项及代码 如下

    9.删除数据

    10. Asc()函数用来返回字符的ASCII码   并且只返回第一个字符  Asc("abc")  =97   

    Ucase()函数:UCase(string),返回 Variant(String)其中包含转成大写的字符串。必要的 string参数为任何有效的字符串表达式。如果 string 包含 Null,将返回Null。只有小写的字母会转成大写,原本大写或非字母之字符保持不变。例:Dim MyWord= UCase("Hello World")' 返回"HELLO WORLD"。

    展开全文
  • 太多的例子讲如何如何实现VC编写动态链接库,VB中声明后使用,但没有一个好的文章来深入探讨这个问题,本文负责解决此类问题。 关键字:VB结构数组,VC,DLL,SAFEARRARY
  • VB传递数组参数

    千次阅读 2008-01-10 01:08:00
    Public Sub 第一个工程() MsgBox "这是我的第一个过程" Dim arrND(0 To 1, 0 To 1) As Variant arrND(0, 0) = "Sample.vsd" arrND(0, 1) = "111" arrND(1, 0) = "222" arrND(1, 1) = "333" CreateDrawing (ar

    Public Sub 第一个工程()
        MsgBox "这是我的第一个过程"
        Dim arrND(0 To 1, 0 To 1) As Variant
        arrND(0, 0) = "Sample.vsd"
        arrND(0, 1) = "111"
        arrND(1, 0) = "222"
        arrND(1, 1) = "333"

        CreateDrawing (arrND())
    End Sub

    Public Sub CreateDrawing(arrNetData As Variant)
        MsgBox arrNetData(0, 1)
    展开全文
  • VB数组编写的例子,求100个学生的平均成绩,程序为了突出数组的作用,因此在程序细节方面没有过多顾及,输入学生成绩时候比较麻烦,需要一个一个输入,有些麻烦。程序异常处理也不太完善。
  • 比如一个数组 Dim A() As Integer ={10,85,36,5,6} 把25插入到其中,前面,后面或者中间部分,怎么做呢
  • vb_生成随机数组_源码

    2021-09-30 05:25:44
    输入一个数字,生成10-99的一个随机数组,大小自定义
  • VB 动态数组,文件读写

    千次阅读 2016-04-06 16:05:20
    例如,下面的代码在E盘VB文件夹下建立Exercise.TXT数据文件,并往文件中输入字符,最后关闭文件: Open   "E:\VB\Exercise.TXT"   For Output As #1   ‘打开文件以便输出 Print #1,”顺序文件...
  • 内容索引:VB源码,算法相关,VB数组 VB数组编写的例子,求100个学生的平均成绩,程序为了突出数组的作用,因此在程序细节方面没有过多顾及,输入学生成绩时候比较麻烦,需要一个一个输入,有些麻烦。程序异常处理也不...
  • 二维数组的位置定位 代码: Private Sub Command1_Click() Dim a(1 To 9, 1 To 9) 先定义a的值范围 For i = 1 To 9 For j = 1 To 9 a(i, j) = "a" & "(" & i & "," & j & ")" Print a(i...
  • vb 数组操作

    2011-11-10 10:16:00
    参数错误,请输入两个可以相乘的矩阵! " End End   If Dim  c()  As   Integer ReDim  c( UBound (a,  1 ),  UBound (b,  2 )) For  i =  0   To   UBound (a,  1 )   For  k =  0   To   ...
  • vb 数组删除元素

    2011-12-12 15:04:00
    Private Sub Command1_Click() Dim n(1 To 100) As Integer ...请输入数组元素个数", "输入框") Print "原始数组为:" For i = 1 To num n(i) = i * 5 + 1 Pri...
  • VB中的数组

    千次阅读 2011-09-16 09:26:39
    5.1 数组的概念 1.引例  求100个学生的平均成绩及超过平均成绩的人数。  如果用一般变量来表示成绩,需要用100个变量,如:mark1、mary2、……mark100。若用数组,可以只用一个来表示mark(1  To ...
  • VB数组应用实例-成绩统计 输入成绩部分: Private Sub Command1_Click() Dim i As Integer Picture1.Cls For i = 1 To N score(i) = Val(InputBox("请输入第" & i & "位学生的成绩")) Picture1.Print score(i); ...
  • vb第八章《数组》课后习题 求指正

    千次阅读 2019-02-08 15:13:00
    1、从键盘上输入10个整数,并放入一个一维数组中,然后将其前5个元素与后5个元素对换,即:第1个元素与第10个元素互换,第2个元素与第9个元素互换……第10个元素与第1个元素互换。分别输出数组原来各元素的值和对换...
  • VB讲课笔记08:数组

    千次阅读 2018-03-12 18:01:30
    VB讲课笔记08:数组学习目标:理解数组的概念、掌握数组的声明、引用方法,掌握数组的使用以及与数组有关的常用算法;了解控件数组的概念、声明和使用。一、数组概念(一)数组定义数组是高级程序设计语言中数据组织...
  • 题目来源:大工慕课 链接 原题:Visual Basic程序设计教程(第二版)龚沛曾主编,高等教育出版社 实验5-10(改) ...输入按钮功能:将具有5个元素的数组各成员送入自定义数组中。 显示输入数据按钮功能...
  • 一个VB数组指针类

    2013-06-07 17:53:45
    所谓绑定,是指在使用该内存地址之前,并不需要申请相应的本地内存缓冲区,也不需要进行内存复制,只是根据该地址凭空构造一个VB数组,并将数组的真实数据地址指向该地址。当然,该类的功能完全可以用CopyMemory函数...
  • 前言 太多的例子讲如何如何实现VC编写动态链接库,VB中声明后使用,但没有一个好的文章来深入探讨这个问题,本文负责解决此类问题。 下载本文示例源代码 大小:125K 1.一般情况 VB中定义为: Private Declare Function F....
  • 矩阵(二维数组)运算,VB6.0源代码编写
  •  '控件数组的Index属性值来输入0-9 End Sub Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer) '键盘输入值保存到定义好的变量中  Select Case KeyCode    Case 13 '回车    Call...
  • "请输入抽奖名单:" & vbCrLf & _   "张飞" & vbCrLf & _   "关与" & vbCrLf & _   "六倍" & vbCrLf & _   "诸葛" & vbCrLf & _   "曹操" & vbCrLf & _   "孙权"  Text2.Text = "幸运观众:" End Sub...
  • 一个VB动态数组例子,输入需要生成的数组大小,自动生成数组,挺简单,还不能应用于实践中,仅供参考。
  • VB数组

    2018-03-31 18:29:00
    1.动态数组 一直给每一个数组赋值,直到空的停止,最多a(0.1.2) 2.排序 Dim a(9) As LongPrivate Sub Command1_Click() Dim i As Long, j As Long, b As Long For i = 1 To 9 For j = 0 To 9 - i 'Debug.Print i...
  • vb数组定义

    万次阅读 2005-06-16 11:56:00
    一、一维数组只有一个下标,数学上形如数列{ai}表示的数据均可用一维...注意数组输入与输出方法。Private Sub Command1_Click() Dim a(100) As Integer Dim s As Integer For i = 1 To 100 a(i) = i Next i End
  • 在学习中遇到从列表框读取多维数组的问题,例如在textbox中有一个二维数组如下 那么如何将其写入数组array1(,)中呢。在这个问题中主要遇到的问题是将文本框中数组按行(vbcrlf)和空格(“ ”)分别split一次...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,489
精华内容 5,795
关键字:

vb输入数组