c# delegate知识

一、引用方法

委托是寻址方法的.NET版本。委托是类型安全的类,它定义了返回类型和参数的类型。委托是对方法的引用,也可以对多个方法进行引用,委托可以理解为指向方法地址的指针。

如:delegate int ReturnIntHandler(int a,int b);//int是返回类型,a和b是引用类型,这是委托执行的方法必须满足如下格式:int method(int param1,int param2);

二、委托

当要把方法传递给其它方法时,需要使用委托。委托是一种特殊类型的对象,其特殊之处在于,我们以前定义的所有对象都包含数据,而委托包含的只是一个或多个方法的地址。

1、声明委托

委托使用关键字 delegate 进行定义。

定义委托基本上就是定义一个新类,所以可以在定义类的任何相同地方定义委托。可以在委托定义上应用常见的访问修饰符:public、private、protected等。其访问作用域也雷同于类。

2、使用委托

为了减少输入量,只需要委托实例,就可以只传递地址的名称。这称为委托推断。



delegate int CalculateMethodInvoker(int x, int y);
    class Program
    {
        static void Main(string[] args)
        {
            CalculateMethodInvoker calculateMethodInvoker = CalculateHelper.Sum;
            int x = 100, y = 200;
            Console.WriteLine("x,y相加:{0}", Calculate(calculateMethodInvoker, x, y));
            calculateMethodInvoker = CalculateHelper.Multiply;
            Console.WriteLine("x,y相乘:{0}", Calculate(calculateMethodInvoker, x, y));
            Console.ReadKey();
        }
        public static int Calculate(CalculateMethodInvoker calculateMethodInvoker, int x, int y)
        {
            //return calculateMethodInvoker(x, y);
            //return calculateMethodInvoker.Invoke(x, y);//是不是当前线程都可以
            IAsyncResult result = calculateMethodInvoker.BeginInvoke(x, y, null, calculateMethodInvoker);//异步,这里只是做展示,EndInvoke类似于async中的await,这里不能实现异步效果
            return calculateMethodInvoker.EndInvoke(result);
        }

    }
    public class CalculateHelper
    {
        public static int Sum(int x, int y)
        {
            return x + y;
        }
        public static int Multiply(int x, int y)
        {
            return x * y;
        }
    }

3、Action<T>和Func<T>委托

除了为每个参数和返回类型定义一个新的委托类型外,还可以使用Action<T>和Func<T>委托。

泛型Action<T>委托表示引用一个void返回类型的方法,没有泛型参数的Action类可调用没有参数的方法,如Action 等价于 delegate void mydelegate;  Action<int,int>等价于delegate void mydelegate(int param1,int param2);

泛型Func<T>委托表示引用一个有返回值的方法,泛型的最后一个参数时Func的返回值类型,如Func<int,int,bool>,等价于delegate bool mydelegate(int param1,int param2);

4、多播委托

委托也可以包含多个方法。这种委托成为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。多播委托识别运算符“-”、“+”、“-=”、“+=”以从委托中增加或删除方法调用。

如:

class Program
    {
        static void Main(string[] args)
        {
            Action<int, int> calFunc = CalculateHelper.Sum;
            calFunc += CalculateHelper.Multiply;//多播加
            int x = 100, y = 200;
            Calculate(calFunc, x, y);
            calFunc =calFunc- CalculateHelper.Multiply;//多播减
            Calculate(calFunc, x, y);
            Console.ReadKey();
        }
        public static void Calculate(Action<int, int> calculateMethodInvoker, int x, int y)
        {
            Console.WriteLine("运行结果:");
            //calculateMethodInvoker(x, y);
            foreach (Action<int, int> item in calculateMethodInvoker.GetInvocationList())//遍历,这里需要转为为当前类型委托
            {
                try
                {
                    item(x, y);//执行委托指向方法
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }

如果通过委托调用的其中一个方法抛出异常,整个迭代就会停止。解决的方法是,使用Delegate类中定义的GetInvocationList()方法获取Delegate对象数组,再使用循环遍历执行,在过程中捕获异常,来继续下一次迭代。

5、匿名方法

匿名方法是用作委托的参数的一段代码。

如:

Action<int, int> calFunc = delegate (int i, int j)
{
    Console.WriteLine("x,y相加:{0}", i + j);
};

在匿名方法中不可使用跳转语句(break、goto或continue),在匿名方法内部不能访问不安全代码,不能访问在匿名方法外部使用的ref和out参数。

三、lambda表达式

C#3.0后,可以使用lambda把实现代码赋予委托,只要有委托参数类型的地方,就可以使用lambda表达式。

如:

Action<int, int> calFunc = (i, j) =>
{
    Console.WriteLine("x,y相加:{0}", i + j);
};

1、参数

lambda表达式有几种定义参数的方式。如果只有一个参数,只写出参数名就足够了。如果除一个参数以外,需要圆括号把参数名括起来。

例子:

Action<int> one = i =>
{
    //method body
};
Action<int, int> two = (i, j) =>
{
    //method body
};

2、多行代码

如果lambda表示只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会隐式添加return。

如:

Func<int> lambdaOne = () => 0;

如果实现代码超过一行,就需要使用return语句显式返回。

如:

Func<int> lambdaOne = () =>

{
    int i = 0;
    i++;
    ++i;
    return i;
};

3、闭包

通过lambda表达式可以访问lambda表达式块外部的变量。这称为闭包。

如:

int param = 10;
Action<int> lambdaSecond = (i) =>
{
    Console.WriteLine(i + param);
};
lambdaSecond(3);
Console.ReadKey();

四、事件

事件基于委托,为委托提供了一种发布/订阅机制。

如:

class Program
    {
        static void Main(string[] args)
        {
            AlarmClock alarmClock = new AlarmClock();
            Student zsStudent = new Student("张三");
            alarmClock.ItsGetUpClockEvent += zsStudent.ItsGetUpClock;
            alarmClock.ItsGetUpClock();
            Student lsStudent = new Student("李四");
            //WeakEventManager<AlarmClock, EventArgs>.AddHandler(alarmClock, "ItsGetUpClockEvent", lsStudent.ItsGetUpClock);
            ////弱事件,System.Windows,WPF中经常用到
            //alarmClock.ItsGetUpClock();
            Console.ReadKey();
        }

    }
    //事件发布类
    public class AlarmClock
    {
        public event EventHandler<EventArgs> ItsGetUpClockEvent;
        public void ItsGetUpClock()
        {
            Console.WriteLine("时间到,起床了!");
            ItsGetUpClockEvent?.Invoke(this, new EventArgs());//判断是否订阅事件
        }
    }
    //事件侦听类
    public class Student
    {
        public string Name { get; set; }
        public Student(string name)
        {
            this.Name = name;
        }
        public void ItsGetUpClock(object sender, EventArgs e)
        {
            Console.WriteLine("{0}关掉闹钟,起床了。", Name);
        }
    }

事件最常用的地方是Winform和Wpf窗体中,而Invoke的经典使用场景如下(非当前线程更改窗体文本):

 private void ShowExecLog(string log)
        {
            if (this.richTextBox1.InvokeRequired)//判断是否是当前线程
            {
                this.richTextBox1.Invoke(new ShowLogHandler(ShowLog), log);
            }
            else
            {
                this.richTextBox1.Text += log;
            }
        }

        public void ShowLog(string log)
        {
            this.richTextBox1.Text += log;
        }

        public delegate void ShowLogHandler(string log);
时间: 2024-10-05 02:49:49

c# delegate知识的相关文章

iOS面试必备-iOS基础知识

近期为准备找工作面试,在网络上搜集了这些题,以备面试之用. 插一条广告:本人求职,2016级应届毕业生,有开发经验.可独立开发,低薪求职.QQ:895193543 1.简述OC中内存管理机制. 答:内存管理机制:使用引用计数管理,分为ARC和MRC,MRC需要程序员自己管理内存,ARC则不需要.但是并不是 所有对象在ARC环境下均不需要管理内存,子线程和循环引用并不是这样.与retain配对使用的是release,retain代表引用计 数+1,release代表引用计数-1,当引用计数减为0时

iOS关于CoreAnimation动画知识总结

一:UIKit动画 在介绍CoreAnimation动画前先简单介绍一下UIKit动画,大部分简单的动画都可以使用UIKit动画实现,如果想实现更复杂的效果,则需要使用Core Animation了:UIKit动画有两种写法:它不仅可以针对视图还可以针对其它控件: 1:第一种写法是利用属性,结合beginAnimations.commitAnimations -(void)animationOfUIKit { UIView *redView=[[UIView alloc]initWithFram

使用live delegate on来解决js对后加载的html失效的问题

今天要写一个前端的东西.每多学一点知识,就可以少写几行代码.几十行代码.几个文件量的代码--这是真的.一直对前端的研究都是停留在遇到问题百度谷歌答案的做法.今天遇到这样一个问题:已经写好的js代码,对ajax加载的html失效了. 用好几组关键字都没有找到答案,最后这组帮我找到了解答的办法: javascript not work on ajax content 很幸运,我来到了:http://stackoverflow.com/questions/10161938/jquery-functio

jQuery绑定事件的四种方式:bind、live、delegate、on

1.jQuery操作DOM元素的绑定事件的四种方式 jQuery中提供了四种事件监听方式,分别是bind.live.delegate.on,对应的解除监听的函数分别是unbind.die.undelegate.off. 2.必备的基础知识: DOM树 示例,这是在browser环境下的一棵模拟DOM树: 我们的页面可以理解为一棵DOM树,当我们在叶子结点上做什么事情的时候(如click一个a元素),如果我们没有人为的设置stopPropagation(Moder Browser), cancel

NSNotificationCenter基础知识

NSNotificationCenter基础知识 Notification的工作机制 1.对应用程序中其他地方发生的事件(比如增加一条数据库记录)感兴趣的对象,会向通告中心(Notification Center,NSNotificationCenter类的实例)注册,从而成为该事件的监听者.在注册过程中,监听者需要指定方法供通告中心在事件发生时调用. 2.给数据库添加记录(或者类似事件)的对象给通告中心发一个通告(NSnotification的实例).该通告对象包括识别通告的标志.发布通告的对

ASP.NET知识重新梳理(三)------C#基础语法

C#基础语法:1.基本语法:无论代码中是否有空格,回车符,tab字符(统称为空白字符),C#编译器都不考虑这些字符: C#字符由一系列语句组成,每个语句由一个分号来结束: C#是一个块结构的语言,所有的语句都是代码块的一部分,这些块用花括号来界定("{"和"}"): C#中的注释:标记注释/*...*/ 单行注释//... 单行注释/// (可以配置VS,在编译项目时,提取这些注释后面的文本,创建一个特殊格式的文本文件,该文件可用于 创建文档说明书): C#代码是区

c#知识梳理

转:http://www.cnblogs.com/zhouzhou-aspnet/articles/2591596.html 本文是一个菜鸟所写,本文面向的人群就是像我这样的小菜鸟,工作一年也辛辛苦苦学习了一年,一直没有机会梳理一下自己的知识,最近花了一些时间整理了一些C#基础知识,也算是对过去的一年做个回顾把~ 文章有点长,请自带瓜子和茶吧,请看下面C#基础知识简单架构图,不可能100%的全面,请见谅啊... 1.值类型和引用类型 1.1堆和栈 简单的说值类型存放在堆栈上面,引用类型的数据存放

iOS 知识-常用小技巧大杂烩

iOS 知识-常用小技巧大杂烩 1,打印View所有子视图 po [[self view]recursiveDescription] 2,layoutSubviews调用的调用时机 * 当视图第一次显示的时候会被调用 * 当这个视图显示到屏幕上了,点击按钮 * 添加子视图也会调用这个方法 * 当本视图的大小发生改变的时候是会调用的 * 当子视图的frame发生改变的时候是会调用的 * 当删除子视图的时候是会调用的 3,NSString过滤特殊字符 // 定义一个特殊字符的集合 NSCharact

知识的总结

在项目中学到的知识和遇到的困难(已经解决的问题) 1,tableView的表头 ……………         tableView.tableViewHeaderVIew  可以添加滚动的视图,这样可以对整个视图的介绍,很多APP的表头的定时滚动 tableView.FootHeaderView  表头,表示对整个视图的总结 ****在cell中传值的过程中,cell会自动帮我们自动添加,不用我们多此添加for循环 2:滚动视图(UIScrollView)的知识的理解 >>scrollView.c