委托的理解和使用

理解:

委托对于新手而言,理解起来还是有困难的,网上也有很多的比喻,在委托和多线程结合时,就是把委托比喻成为一个中介商,在线程交互Ui控件的数据时,你会发现,需要用到委托,在新线程调用me.invoke(委托,参数,参数),于是乎,Me.invoke就将数据传到ui控件,这是通过委托的方式,就有新线程不能直接操控控件,通过委托人,将数据送到控件。假如不用委托,那么报出的错误时,从不是创建线程访问控件。而me.invoke实际上就是将线程转为创建线程来访问控件,控件的创建线程就是窗体或者控件.invoke.都可以,一句话就是哪个对象调用invoke就把委托对应的过程回调到创建对象所在的线程执行。.net也推荐这种方式进行跨线程的控件操作。
委托实际上不仅仅用于线程,委托实质只是一个类型delegate,而这个类型封装了函数地址,你看到的addressof关键字就是进行函数地址的获取。拥有了函数地址,我们就能对其进行回调。用回调的方式的还有事件的方式。addhandler 事件,addressof 过程。

使用

1.多线程结合委托操作控件
本节不是主讲多线程,所以不会多赘述它。

Imports System.Threading
Public Class Form1
    Delegate Sub Mydelegate(data As String) '声明一个委托
    Private Sub RefereshCtrl(data As String) '委托对应的过程
        Label1.Text = data
    End Sub
    Private Sub NewThread() '创建的新线程
     
        For i = 0 To 100


            Me.Invoke(New Mydelegate(AddressOf RefereshCtrl), i.ToString) '使用委托方式回调刷新控件的过程
            Thread.Sleep(1000) '延时一秒刷新
        Next
    End Sub
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim t As New Thread(AddressOf NewThread)
        t.Start() '开始线程
    End Sub
End Class

在这里插入图片描述
很显然lable用了委托后能够刷新数据,不卡ui.
2.委托用于Linq
使用linq前需要了解lambda即匿名函数。
lambda分为单行lambda和多行lambda

  Dim testsinglelambda = Sub(test As String) Debug.WriteLine(test)
        Dim testMutillinelambda = Sub(test As String)
                                      Debug.WriteLine(test)
                                  End Sub

        testsinglelambda("这是一个单行lambda")

        testMutillinelambda("这是一个lambda")

在这里插入图片描述
如上即是简单的lambda了。若要有返回值的lambda就用类似dim fuc=function() return xx
即是把sub改为funciton,加个返回值,和我们定义的sub和function但它没有名称,所以称为匿名。
到这里你会问,lambda和委托是什么关系呢?
这里我用反射给你看看它的真面目。

  Dim testsinglelambda = Sub(test As String) Debug.WriteLine(test)
        Dim lambdatype = testsinglelambda.GetType
        Dim lambdabasetype = lambdatype.BaseType
        Dim lambdabasetypebasetype = lambdabasetype.BaseType

    Debug.WriteLine("lambda继承:{0}->{1}->{2}", lambdatype.Name, lambdabasetype.Name, lambdabasetypebasetype.Name)

这里我用反射获取其父类的父类。
在这里插入图片描述
继承关系如图,匿名委托->多播委托->委托。
所以我们可以知道lambda本身就是属于委托类型,也就不奇怪于lambda.invoke这个方法了。
你也可以用lambda替代me.invoke中的委托即me.invoke(lambda)
在.net中内置了多个action,和多个func,这些都属于委托类型。linq也是基本传入这些参数类型的委托。
一个简易的linq示例如下。

 Dim linqlist = Enumerable.Range(0, 80) '生成80个数字
        Dim result = linqlist.Where(Function(x) x > 50) '筛选大于50的整数
        For Each item As Integer In result
            Debug.Write(item & vbTab) '输出结果
        Next

在这里插入图片描述
输出结果如图。这里的委托返回的是一个Boolean值,linq通过判断这个值来对集合进行一个筛选。

这也可以启发我们,用委托作为参数传入到过程中,我们不需要关注外界怎样的过程只需要使用委托返回的结果进行判断即可。
接下来我做个简单的示例模仿Linq筛选条件的过程

 Private Function 筛选(Of T)(sourcelist As IEnumerable(Of T), fuc As Func(Of T, Boolean)) As IEnumerable(Of T)
        Dim result As New List(Of T)

        For Each item As T In sourcelist
            If fuc(item) Then
                result.Add(item)
            End If
        Next
        Return result
    End Function
     Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        Dim linqlist = Enumerable.Range(0, 80)
        Dim result = 筛选(Of Integer)(linqlist, Function(x) x > 70)
        For Each item As Integer In result
            Debug.Write(item & vbTab)
        Next

    End Sub

这是一个筛选x>70的模仿Linq。
结果:
在这里插入图片描述
这里用了泛型目的是让筛选的过程可以适用于所有类型,再配上泛型委托func简直就是能够适用于所有需要筛选的过程。
看到这里,我相信你能看到了委托的强悍的地方,那就是提供一个不限思想的空间给用户写过程,而它只需要用invoke即可,提高了代码的复用性,提高了开发效率,一套代码多处使用。再加上委托用的是lambda写起来又很方便。
舒服到无法自拔的操作,强烈推荐。
由于篇幅有限,使用委托的地方实在太多这里仅用了几个经典的地方使用它,委托你甚至可以用于控件的属性。具体得给读者开发了。
此处涉及内容有反射,lambda,linq,多线程,希望不太懂的去了解一下相关知识

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值