C#知识(4)

C#知识(4)

1.委托

本来我是想先聊聊事件的,但是没有委托的事件是不完整的,所以我们还是先聊一下委托,

如果你和我一样是C++和C#双开的,你一定知道C++里面有一个概念叫做指针,而指针中有一类比较特殊的叫做函数指针,函数指针的作用其实就是让一个函数变成一个变量,让函数变成方法的参数,从而指定方法根据不同情况使用不同函数。

其实C#中委托和函数指针的作用几乎一模一样,,又或者说就是一样的。先来看一下用法吧。

using System;
class program
{
    public static void Ashow(string a)
    {
        Console.WriteLine(a+"我是A");
    }

    public static void Bshow(string b)
    {
        Console.WriteLine(b+"我是B");
    }

    public static void Cshow(string c)
    {
        Console.WriteLine(c+"我是C");
    }

    public delegate void Show(string s);

    public static void Getshow(Show a,string s)
    {
        a(s);      
        //a.Invoke(s);                                                       //这样写也行
    }

    public static void Main(string[] argv)
    {
        string a = "hhh";
        Show oneshow = Ashow;                                                //可以直接赋值
        Show twoshow = new Show(Bshow);                                      //也可以new了之后再将函数名按照参数传进去
        Show threeshow = new Show(Cshow);
        Getshow(oneshow,a);
        Getshow(twoshow,a);
        Getshow(threeshow,a);
        Show allshow = null;
        allshow += oneshow;                                                  //+=后面可以跟方法名
        allshow += twoshow;
        allshow += threeshow;
        Getshow(allshow,a);
    }
}

委托的使用非常简单,声明的时候使用一个delegate关键词就行。使用的话可以把实例出来的委托名直接作为函数名使用。也可作为参数传给其他的方法。

接下来我们讨论以下委托的深层次的东西(来源于《clr via C#》)

使用起来简答的东西内部的实现细节就会越复杂,为了让委托好用,编译器和clr为我们干了太多事了(感动)(如果不知到clr是什么的,我回头会写,你可以先当它是C#虚拟机)

当我们用以下语句定义一个委托时

public delegate void Show(string s);

编译器会将这行代码定义成下面这样一个类

internal class Show:System.MulticastDelegate
{
    public Show(object target, IntPtr method);
    public virtual void Invoke(Int32 value);
    public virtual IAsyncResult BeginInvoke(Int32 value, AsyncCallback callback, Object @object);
    public virtual voidEndInvoke(AsyncCallback result);
}

BeginInvoke和EndInvoke先不谈,先聊一下构造器和Invoke函数

构造器,其实就是C++的构造函数,我们首先注意到的是它的两个参数,既然构造函数有参数,自然是要用这些函数来初始化类中的成员的,所有的委托都是继承于System.MulticastDelegate这个类,而System.MulticastDelegate这个类又是派生自System.Delegate类,这其中有一些历史原因,这里就不展开说了,反正就是继承下来的成员有三个比较重要的:

image-20220622232515967

所以构造器的两个参数分别是target,methodPtr。

最后一个字段invocationList则是在我们像allshow那样将一堆方法构造成一个委托链时会用到,他就像一个链表分别去装构造这个委托的所有方法或委托。

接下来是Invoke方法,这个方法在委托被定义的时候被定义,通过调用target和methodPtr字段在指定的对象上调用包装好的回调方法。所以通过委托调用方法时,其实就是在调用委托类的Invoke方法,所以你直接在编程的时候就直接写成a.Invoke(s)也可以。

最后就是在System.Delegate类中有个方法可以直接取得invocationList中的值。比如下面这个例子就是其中的一种用法。

Delegate[] array = allshow.GetInvocationList();
foreach (var every in array)
{
    Console.WriteLine(every.Method.Name);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值