C#基础——委托

摘要:
以下所写是个人对委托的理解,为了加深对委托的理解和记忆,特地写下来。C#中常使用委托做回调。委托其实是一个类,在编译之后的编译文件中可以看到,委托的类型是class。C#和CLR都允许引用类型的协变性和逆变性。使用Delegate的Combine方法来构建委托链,委托链其实也是一个委托。

以下所写是个人对委托的理解,为了加深对委托的理解和记忆,特地写下来。

委托的介绍:

委托和事件是一对好搭档,事件在之后的文章中做介绍。C#中常使用委托做回调。

委托其实是一个类,在编译之后的编译文件中可以看到,委托的类型是class。

C#和CLR都允许引用类型的协变性和逆变性。

协变性:指方法的返回类型派生的一个类型。

逆变性:指方法的参数可以是委托的参数类型的基类。

注意:斜边性和逆变性只能作用于引用类型,不能作用于值类型和void。值类型和void之所以不支持协变性和逆变性是因为它们的存储结构是变化的,而引用类型的存储结构始终是一个指针。

1.声明委托

使用关键字:delegate,

如下所示:这里声明了一个没有返回值的委托。

public delegate void ConsloleWrite(string str);

2.使用委托

 public classProgram
    {
        static void Main(string[] args)
        {
            Console.Write("请输入:");
            string str =Console.ReadLine();
            TestDelegate td = newTestDelegate();
            td.DelegatePrint(Convert.ToInt32(str), print);
        }
        public static void print<T>(T str)
        {
            Console.WriteLine(str);
            Console.ReadKey();
        }
    }
   public classTestDelegate {
        public void DelegatePrint<T>(T str,ConsloleWrite<T>write) {
            write(str);
        }
    public delegate void ConsloleWrite<in T>(T obj);
    }

3.使用委托回调很多方法(委托链)

委托链是由委托对象构成的一个集合。

使用Delegate的Combine方法来构建委托链,委托链其实也是一个委托。

委托链有两种写法,分别使用Combine、Remove方法,和+=、-=符号。+=和-=符号是为了简化委托链的使用,其实内部还是调用了Combine和Remove方法。

废话不多说,直接贴上代码……

 public classProgram
    {
        static void Main(string[] args)
        {
            Console.Write("请输入:");
            string str =Console.ReadLine();
            ConsoleWrite cw = null;
            //委托链的写法1
            cw = (ConsoleWrite)Delegate.Combine(newConsoleWrite(print), cw);
            cw = (ConsoleWrite)Delegate.Combine(newConsoleWrite(print2), cw);
            cw = (ConsoleWrite)Delegate.Remove(cw, newConsoleWrite(print2));
            //委托链写法2
            //cw += new ConsoleWrite(print);
            //cw += new ConsoleWrite(print2);
            ////移除委托链中的委托对象
            //cw -= new ConsoleWrite(print2);
            TestDelegate td = newTestDelegate();
            td.DelegatePrint(str, cw);
            Console.ReadKey();
        }
        public static void print(stringstr)
        {
            Console.WriteLine("print:"+str);
        }
        public static void print2(stringstr)
        {
            Console.WriteLine("print2:" +str);
        }
    }
    public classTestDelegate
    {
        public void DelegatePrint(stringstr, ConsoleWrite write)
        {
            if (write != null)
            {
                write(str);
            }
        }
    }
    public delegate void ConsoleWrite(string obj);

最后在说一句,委托其实就是类,只要能声明类的地方就能声明委托。

免责声明:文章转载自《C#基础——委托》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇类别联动下拉菜单修改JavaScript脚本并离线编译后将数据同步到Web和Web app下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Mac下卸载删除nvm和node

nvm是Mac下的node管理工具,有点类似管理Ruby的rvm,nvm是一个独立于node/npm的外部shell脚本。...

PostGIS拓扑:pgRouting最短路径分析

由于我们没有创建topo所需要的所有字段,有部分是用现有字段替代的,因此,在调用最短路径分析函数时,需在sql中显示指定这些字段。...

MySQL锁详解

MySQL锁详解update语句执行流程MySQL的锁介绍按照锁的粒度来说,MySQL主要包含三种类型(级别)的锁定机制:全局锁:锁的是整个database。由MySQL的SQLlayer层实现的表级锁:锁的是某个table。由MySQL的SQLlayer层实现的行级锁:锁的是某行数据,也可能锁定行之间的间隙。...

ESXi挂载NFS共享存储

使用万兆交换机,ESXi使用NFS协议连接存储。本文介绍的是通过NFS协议挂载共享存储上的VS01卷,共享存储上已经赋予ESXi主机访问该卷的权限。...

winform中 跨线程启动UI

C#的winform程序中,是不可以从UI窗口主线程之外的线程去直接操作窗口控件的。确切的解释是,不能从创建控件的线程以外的线程去处理控件的操作,比如修改属性等。方法二,通过Control.Invoke调用委托的方式来执行。...

oracle触发器调试

如果触发器执行成功,不会出现第4个图,不成功,会出现数据调试信息,具体报错位置会定位到。F7单步执行4.出错时,会出现调试数据,双击调试数据,可以复制出来...