C# 委托简介(delegate、Action、Func、predicate)

委托是一种定义方法签名的类型。当实例化委托时,您可以将其实例与任何具有兼容签名的方法相关联。您可以通过委托实例调用方法。

如何使用委托?

1、定义委托类型

[访问修饰符]  delegate  返回类型  委托名(形参);

2、声明委托对象

委托名 委托实例名;

3、创建委托对象

委托实例名 = new 委托名(某个类的方法)

4、使用委托调用方法

委托实例名(实参)

委托注意事项:

1、委托和方法必须具有相同的签名。

2、委托可以调用多个方法,即一个委托对象可以维护一个可调用方法的列表而不是单独的一个方法,称为多路广播(多播)。

3、使用+=和-=运算实现方法的注册和注销

写法:

1、委托  委托名  =  new  委托(会调用的方法名);

     委托名(参数);

    CallobjCall =newCall(SimpleMath.Multiply);

   CallobjCall1 =newCall(newSimpleMath().Divide);

2、委托  委托名  =  会调用的方法名;

     委托名(参数);

   CallobjCall =SimpleMath.Multiply;

   CallobjCall1 =newSimpleMath().Divide;

3、匿名方法

      委托  委托名  =  delegate(参数){会调用的方法体};

      委托名(参数);

     CallobjCall  =delegate(inta,intb) { return a * b; };

     CallobjCall1 =delegate(inta,intb) { returna / b; };

4、lambda表达式

      委托  委托名 = ((参数1,。。参数n)=>{会调用的方法体});

      委托名(参数);

    CallobjCall = ((inta,intb) => {returna * b; });

    CallobjCall1 = ((inta,intb) => {returna / b; });

5、用Action和Func,第一个无返回值

     Func<参数1, 参数2, 返回值> 委托名 = ((参数1,参数2) => {带返回值的方法体 });

     返回值 = 委托名(参数1,参数2);

    Action obj = ((a, b) => {Console.WriteLine(a * b); });

     obj(5, 3);

     Func objCall = ((a, b) => {returna * b; });

    intresult = objCall(5, 3);

    Func objCall1 = ((a, b) => {returna / b; });

    intresult1 = objCall1(5, 3);

1.委托的声明

  (1). delegate

        delegate是我们常用到的一种声明。

   Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。

   例:public delegate int MethodtDelegate(int x, int y);表示有两个参数,并返回int型。

 (2). Action

        Action是无返回值的泛型委托。

   Action表示无参,无返回值的委托。

   Action 表示有传入参数int,string无返回值的委托。

   Action 表示有传入参数int,string,bool无返回值的委托。

        Action 表示有传入4个int型参数,无返回值的委托。

    Action至少0个参数,至多16个参数,无返回值。

   例:

        public void Test(Action action,T p)

        {

             action(p);

        }

  (3). Func

   Func是有返回值的泛型委托

   Func 表示无参,返回值为int的委托

   Func 表示传入参数为object,string 返回值为int的委托

   Func 表示传入参数为T1,T2,T3(泛型)返回值为int的委托

   Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

        例:

        public int Test(Funcfunc,T1 a,T2 b)

        {

             return func(a, b);

        }

   (4) .predicate

   predicate是返回bool型的泛型委托

   predicate 表示传入参数为int 返回bool的委托

   Predicate有且只有一个参数,返回值固定为bool

   例:public delegate bool Predicate (T obj)

2.委托的使用

(1).Delegate的使用

        public delegate int MethodDelegate(int x, int y);

        private static MethodDelegate method;

        static void Main(string[] args)

        {

            method = new MethodDelegate(Add);

            Console.WriteLine(method(10,20));

            Console.ReadKey();

        }

        private static int Add(int x, int y)

        {

            return x + y;

        }

  (2).Action的使用

        static void Main(string[] args)

        {

            Test(Run,"Hello World!");

            Test(Run, 1000);

            //使用Lambda表达式定义委托      

            Test(p => { Console.WriteLine("{0}", p); }, "Hello World");     

            Console.ReadKey();

        }

        public static void Test(Action action, T p)

        {

            action(p);

        }

        private static void Run(string s)

        {

            Console.WriteLine(s);

        }

        private static void Run(int s)

        {

            Console.WriteLine(s);

        }

    可以使用 Action 委托以参数形式传递方法,而不用显式声明自定义的委托。

      封装的方法必须与此委托定义的方法签名相对应。 也就是说,封装的方法必须具有四个均通过值传递给它的参数,并且不能返回值。

(3).Func的使用

        static void Main(string[] args)

        {

            Console.WriteLine(Test(Run,100,200));

            Console.ReadKey();

        }

        public static int Test(Func func, T1 a, T2 b)

        {

            return func(a, b);

        }

        private static int Run(int a, int b)

        {

            return a + b;

        }

 (4). predicate的使用

  泛型委托:表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。

        static void Main(string[] args)

        {

            Point[] points = { new Point(100, 200),

            new Point(150, 250), new Point(250, 375),

            new Point(275, 395), new Point(295, 450) };

            Point first = Array.Find(points, Product);

            Console.WriteLine("Found: X = {0}, Y = {1}", first.X, first.Y);

            Console.ReadKey();

        }

        private static bool Product(Point p)

        {

            if (p.X * p.Y > 100000)

            {

                return true;

            }

            else

            {

                return false;

            }

        }

  使用带有 Array.Find 方法的 Predicate 委托搜索 Point 结构的数组。如果 X 和 Y 字段的乘积大于 100,000,此委托表示的方法 ProductGT10 将返回 true。Find 方法为数组的每个元素调用此委托,在符合测试条件的第一个点处停止。

 3.委托的清空

  (1).在类中申明清空委托方法,依次循环去除委托引用。

         方法如下:

        public MethodDelegate OnDelegate;               

        public void ClearDelegate()       

        {           

            while (this.OnDelegate != null)

            {               

                this.OnDelegate -= this.OnDelegate; 

            }       

        }

  (2).如果在类中没有申明清空委托的方法,我们可以利用GetInvocationList查询出委托引用,然后进行去除。

  方法如下:


         public delegate void MethodDelegate();

        public static MethodDelegate OnDelegate;

        static void Main(string[] args)

        {

            if (OnDelegate != null)

            {

                Delegate[] dels = test.OnDelegate.GetInvocationList();

                for (int i = 0; i < dels.Length; i++)

                {

                    test.OnDelegate -= dels[i] as MethodDelegate;

                }

            }

        }

4.委托的特点

  委托类似于 C++ 函数指针,但它们是类型安全的。

  委托允许将方法作为参数进行传递。

  委托可用于定义回调方法。

  委托可以链接在一起;例如,可以对一个事件调用多个方法。

  方法不必与委托签名完全匹配。

5.总结:

    Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型

  Func可以接受0个至16个传入参数,必须具有返回值

  Action可以接受0个至16个传入参数,无返回值

  Predicate只能接受一个传入参数,返回值为bool类型

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,573评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,549评论 18 399
  • 1.委托的声明 Delegate可以指定返回值类型;Aciton无返回值类型;Func的最后一个参数表示返回值类型...
    混世小码农阅读 355评论 0 1
  • 1. [C#语言基础]请简述拆箱和装箱。 答: 装箱操作: 值类型隐式转换为object类型或由此值类型实现的任何...
    胤醚貔貅阅读 4,762评论 1 29
  • 之前做过一些关于android播放器的开发工作,当时懵懂无知,只知道一个ffmpeg,然后就费劲巴拉的用ndk把f...
    ME_HK阅读 18,602评论 7 9