VB.net学习笔记九委托


一、委托

委托取自现实生活中之意:委派某人去干某事。如,某人委托律师帮自己打官司。

因为有些时候,自己不能做某事,于是让派人帮做事。或者实现功能较为麻烦。


实际上,它就是一个回调函数。

A--------->B------------>C

A调用了B,而B中又调用了C,但这不是简单的调用。

因为A在调用B的同时,把C的函数地址传递给了B,意思就是让B调用指定的函数地址去调用(即调用C)。

从而我们可以知道:B接收一个函数地址C;

C可以自己定义功能,只要最后把本身的函数地址提供即可。

于是,B常被固定代码被使用,只要保留接收函数地址参数这个接口即可。通常B被作为固定的算法功能模块,很少改变。

而C经常被改变,它改变是因为每个人的要求不一样。

关于回调 函数请参看:http://blog.csdn.net/dzweather/article/details/9018097


对于回调方法,.NET环境使用的底层机制就是委托,VB.net在实现Event,RaiseEvent,WithEvents,Handles关键字时,

就在后台使用委托。


下面一个实例来看一下委托的步骤。

一个排序功能的通用例程,由于排序的数据也可能是对象,对象怎么比较呢?

通用全程就是上面的B,而数据的比较就是自定义的功能了即C。只要在A处调用时把C的函数地址传给B即完成了对象的比较。

通过添加模块来完成下面代码。



1、声明委托

应该委托谁呢?我们应该先指明它。用Delegate来声明,

声明的是个方法的签名,即类似于这样的方法签名的函数地址都可以被委托接收。

Module Sort
  '声明委托。类似C++的函数指针类型
  Public Delegate Function Compare(ByVal v1 As Object,ByVal v2 As Object) As Boolean

  '......
End Module

上面的方法签名是:f(object,object),这是声明要接收的函数地址的类型,即C的函数形式也应该是这样形式。

如果C的函数形式是f(objcet),则上面(即B)是不能接收这样的参数的。这是为接收回调用函数地址作准备。



2、使用委托数据类型

有了前面的声明,就可定义B了,在B中定义一个接收委托的数据类型(即函数地址类型)


上面接收的参数有两个,第一个是传来的数据,第二个是下一步进行调用C的函数地址的类型,可以看到是当作一类型来处理。

ByVal GreeterThan As Compare ‘Compare就是前面的声明的委托,说明传来传来参数必须符合Compare的签名。


另外,上面使用Invoke方法从代码中调用委托,即调用C。



3、实现委托方法

下面就是完成C的工作,因为原程序中已经有这个CompareAge这个方法,可以通过重载,实现C的功能。

重载后CompareAge(object,object)就符合方法签名。

    Public Shared Function CompareAge(ByVal Person1 As Person,ByVal Person2 As Person) As Boolean
        Return Person1.Age > Person2.Age
    End Function

    Public Shared Function CompareAge(ByVal Person1 As Object,ByVal Person2 As Object) As Boolean '用的是这个,因为上面有同名,进行重载
        Return CType(Person1,Person).Age > CType(Person2,Person).Age
    End Function
注意:这里的方法签名,方法的名称并不重要,重要的是参数的个数、顺序、类型、及返回值。



4、正式调用

有了上面一环扣一环的要求。现在的工作是,怎么让B有权限去调用C。

下面调用时,就把地址(通过Addressof取得方法的地址),传递给B。这样B才会认得地址去完成C的功能。

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

        myPeople(0) = New Person("Fred",#7/9/1960#)
        myPeople(1) = New Person("Mary",#1/21/1955#)
        myPeople(2) = New Person("Sarah",#2/1/1960#)
        myPeople(3) = New Person("George",#5/13/1970#)
        myPeople(4) = New Person("Andre",#10/1/1965#)

        DoSort(myPeople,AddressOf Person.CompareName)
    End Sub



5、看一下这个过程的流程。

1处就是C功能,在2(A)中把这个C功能的地址提取出来(Addressof),通过2中的调用用参数传递给3(B)。

关键在于B,这个设计好了,代码的重用性就高了。我们添加的只是C的简单适合自己的功能。










二、组件

组件与类的概念相似,基本上可以互换。但组件支持图形设计器,意味着可以利用工具箱等来播放操作来提供组件的代码。


组件与控件的区别


一般把Control翻译成控件,把Component翻译成组件。

控件就是具有用户界面的组件。

要说的具体一点,就得回顾早期 Windows 的历史根源,当时控件指任何子窗口——按钮、列表框、编辑框或者

某个对话框中的静态文本。

从概念上讲,这些窗口——控件——类似用来操作收音机或小电器的旋钮和按钮。随着控件数量的增加(组合框、

日期时间控件等等),控件逐渐成为子窗口的代名词,无论是用在对话框中还是用在其它种类的主窗口中。没过多

久 BASIC 程序员开始编写他们自己专用的控件,自然而然地人们便想到共享这些控件。

共享代码的方法之一是通过磁盘拷贝,但那样显然效率低下。必须要有一种机制使开发者建立的控件能够在其它程序员的

应用中轻而易举地插入,这便是VBA控件,OLE控件,OCX和最后ActiveX 控件的动机。

这就是控件和组件之间产生混淆之所在。

因为为了解决控件的可复用问题,所有这些技术必须首先解决更为一般的组件重用问题。(COM,如果你还记得它的话,

意思是组件对象模型)。在软件行话中,组件这个术语指任何可复用的对象或任何可与其它对象交互的代码体。子程序的

发明,曾经一度成为程序员趋之若鹜的软件工程圣杯:一种统一的编程理论,它使程序员从基本构建块——也就是用所选语

言编写的各种组件建立大型系统。

从子程序演变到OOP,到DLLs,再到COM,再到.NET框架的每一种新的编程范例都代表了一种不同的提供可重用性的方案。

VBX使用DLLs的固化名称。COM使用接口和IUnknown。.

NET框架使用微软的中间语言(MSIL)层和公共语言运行时(CLR)来提供统一的粘合。


因此,控件是组件的一个主要样本(并且历史上曾驱动着组件的开发),控件又不仅仅是唯一的一种组件。组件不需要显示

任何信息或用户界面。组件可能实现科学计算,收集性能数据,计算1971年1月1日到现在的毫秒数,仰或是读取布什总统

竞选活动保险箱里的美金数。


下面摘自:http://blog.csdn.net/btwsmile/article/details/6658220

===========================================

组件(Component)比控件(Control)涵盖的范围要广,控件是组件的一种。

什么是组件?可以把它理解成一个可以反反复复使用的模块。就是说只要一个模块能够重用,它就可以称当上一个组件,而不用在乎这个模块有没有“外型”。

控件不仅是可以“重用”的模块,而且还有“外型”。平常看到的除了UI对象之外的程序子窗体,都算得上控件。UI对象有3种:菜单、工具栏、快捷键,除开它们其它可以看得到的子窗体都是控件,比如按钮、标签、单选框、复选框、列表、树型选单等。实际上最能体现“控件”本意的就是按钮了。可以把整个程序当作一台收音机,按钮用来控制这台收音机的一些功能。

总结一下:(1)控件是组件的一种,全称叫“控制组件”;(2)控件一定有UI外型,一定看得到。

最后,顺便提一提Windows窗口消息与控件的联系。Windows的窗口消息用宏WM_XX来表示,比如WM_PAINT,WM_CREATE等。它可以分为三大类:标准消息、命令消息、控件通知消息。所谓标准消息,就是除去WM_COMMAND之外,所有WM_XX消息的统称;命令消息也就是WM_COMMAND消息;控件通知消息外型伪装成WM_COMMAND,是控件向自己的父窗口通知某种情况。

这三类消息的“来源”是不相同的,标准消息来源最广,但不太方便归类。命令消息来自于UI对象,正如上面所说,也就是来自菜单、工具栏、快捷键。命令消息的作用,就是发出命令让程序做什么,这个过程点点鼠标或者按按快捷键就能搞定。控件通知消息(Control Notification)顾名思义就是控件向父窗体报告某种情况。除开UI对象和控件发出的消息之外,剩下的消息全部都是标准消息。











三、Lambda表达式

自VB.net9.0后引入Lambda表达式,它的主要驱动力是LINQ。

使用Lambda可以在一行代码中创建简单的匿名方法及其委托。例:

    Function add(ByVal i As Integer) As Integer
        Return i + 10
    End Function

上面一个函数可以简写与下面一行代码,然后再来显示效果。
    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        Dim myLambda = Function(i As Integer) i + 10
        TextBox1.Text = myLambda(33)
    End Sub


VB2010前,只能使用返回一个值的单行Lambda表达式,不能创建定义了Sub的Lambda表达式或多行Lambda表达式。

而VB2010中,VB.net改进了这些。

这是一个Sub,且多行的调用。

Public Sub SocketReceiveData(ByVal Data() As Byte,ByVal DataLen As Integer,ByVal RemoteIPEndPoint As System.Net.IPEndPoint)
        Me.Invoke(Sub()
                  SocketElv.Items.Add(New ListViewItem(New String() {Now.ToString("yyyy-MM-dd HH:mm:ss"),RemoteIPEndPoint.ToString,BitConverter.ToString(Data)},"Log"))
                  End Sub)
End Sub


这是另一个多行,无返回值的调用例:

    Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
        '多行的另一例:
        Dim myLambda = Sub(i As Int32)
                           MsgBox(i)
                       End Sub
        myLambda(4)
    End Sub

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Format[$] ( expr [ , fmt ] ) format 返回变体型 format$ 强制返回为文本 -------------------------------- 数字类型的格式化 --------------------------------     固定格式参数:     General Number 普通数字,如可以用来去掉千位分隔号     format$("100,1
VB6或者ASP 格式化时间为 MM/dd/yyyy 格式,竟然没有好的办法, Format 或者FormatDateTime 竟然结果和系统设置的区域语言的日期和时间格式相关。意思是尽管你用诸如 Format(Now, "MM/dd/yyyy"),如果系统的设置格式区域语言的日期和时间格式分隔符是"-",那他还会显示为 MM-dd-yyyy     只有拼凑: <%response.write
在项目中添加如下代码:新建窗口来显示异常信息。 Namespace My ‘全局错误处理,新的解决方案直接添加本ApplicationEvents.vb 到工程即可 ‘添加后还需要一个From用来显示错误。如果到这步还不会则需要先打好基础啦 ‘======================================================== ‘以下事件
转了这一篇文章,原来一直想用C#做k3的插件开发,vb没有C#用的爽呀,这篇文章写与2011年,看来我以前没有认真去找这个方法呀。 https://blog.csdn.net/chzjxgd/article/details/6176325 金蝶K3 BOS的插件官方是用VB6编写的,如果  能用.Net下的语言工具开发BOS插件是一件很愉快的事情,其中缘由不言而喻,而本文则是个人首创,实现在了用V
Sub 分列() ‘以空格为分隔符,连续空格只算1个。对所选中的单元格进行处理 Dim m As Range, tmpStr As String, s As String Dim x As Integer, y As Integer, subStr As String If MsgBox("确定要分列处理吗?请确定分列的数据会覆盖它后面的单元格!", _
  窗体代码 1 Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 2 Dim path As String, hash As String 3 For Each fil
  Imports MySql.Data.MySqlClient Public Class Form1 ‘ GLOBAL DECLARATIONS Dim conString As String = "Server=localhost;Database=net2;Uid=root;Pwd=123456;" Dim con As New MySqlConnection
‘導入命名空間 Imports ADODB Imports Microsoft.Office.Interop   Private Sub A1() Dim Sql As String Dim Cnn As New ADODB.Connection Dim Rs As New ADODB.Recordset Dim S As String   S = "Provider=OraOLEDB.Oracl
Imports System.IO Imports System.Threading Imports System.Diagnostics Public Class Form1 Dim A(254) As String    Function ping(ByVal IP As Integer) As String Dim IPAddress As String IPAddress = "10.0.
VB运行EXE程序,并等待其运行结束 参考:https://blog.csdn.net/useway/article/details/5494084 Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long Pr
今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBirthday, SecEmail, UserMob, UserSex, RealNameFirst, RealName, CheckCardID, CheckCardType, Contactemail
在VB6.0中,数据访问接口有三种: 1、ActiveX数据对象(ADO) 2、远程数据对象(RDO) 3、数据访问对象(DAO) 1.使用ADO(ActiveX Data Objec,ActiveX数据对象)连接SQL Server 1)使用ADO控件连接 使用ADO控件的ConnectionString属性就可以连接SQL Server,该属性包含一个由分号分隔的argument=value语
注:大家如果没有VB6.0的安装文件,可自行百度一下下载,一般文件大小在200M左右的均为完整版的软件,可以使用。   特别提示:安装此软件的时候最好退出360杀毒软件(包括360安全卫士,电脑管家等,如果电脑上有这些软件的话),因为现如今的360杀毒软件直接会对VB6.0软件误报,这样的话就可能会在安装过程中被误报阻止而导致安装失败,或者是安装后缺乏很多必须的组件(其它的杀毒软件或安全卫士之类的
Private Sub Form_Load() Call conndb End Sub Private Function conndb() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim strCn, sql As String Dim db_host As String Dim db_user As String
  PPSM06S70:  Add  moddate  EDITSPRINTJOB:  MAX(TO_CHAR(ETRN.MODDATE, ‘yyyy/mm/dd/HH24:MI AM‘)) ACTUAL_SHIPDATE   4.Test Scenario (1) :Query SQL Test DN:8016578337 SELECT CTRN.TKCTID TRUCK_ID,        
  沒有出現CrystalReportViewer時,須安裝CRforVS_13_0. 新增1個數據集,新增1個數據表,添加二列,列名要和資料庫名一樣. 修改目標Framework 修改app.config, <startup >改成<startup useLegacyV2RuntimeActivationPolicy ="true">  CrystalReport1.rpt增加數據庫專家 在表單
Imports System.Threading Imports System Public Class Form1 Dim th1, th2 As Thread Public Sub Method1() Dim i As Integer For i = 1 To 100 If Me.Label1.BackColor =
Friend Const PROCESS_ALL_ACCESS = &H1F0FFF = 2035711 Friend Const PROCESS_VM_READ = &H10 Friend Const PROCESS_VM_WRITE = &H20 Friend Const PAGE_READONLY = &H2 Friend Const PAGE_READWRITE = &H4 Friend
以下代码随手写的 并没有大量测试 效率也有待提升 如果需要C#的请自行转换 Function SplitBytes(Data As Byte(), Delimiter As Byte()) As List(Of Byte()) Dim i = 0 Dim List As New List(Of Byte()) Dim bytes As New
Imports System.Data.SqlClient Public Class Form1 REM Public conn1 As SqlConnection = New SqlConnection("server=.; Integrated Security=False;Initial Catalog= mydatabase1; User ID= sa;password")