C# 委托应用总结

一、什么是委托

委托基础拓展:http://www.cnblogs.com/yangyancheng/archive/2011/04/21/2024145.html

1.1官方解释

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

1.2个人理解

委托就是执行方法(函数)的一个类。

事件是一种特殊的委托。

二、如何申明委托

2.1 delegate

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

2.2 Action

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

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

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

2.3 Func

Func是有返回值的泛型委托

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

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

2.4 predicate

predicate 是返回bool型的泛型委托

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

2.5 四者之间的区别

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

Action至少1个参数,至多4个参数,无返回值,

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

Predicate至少1个参数,至多1个参数,返回值固定为bool

三、如何使用委托

3.1 Labmda表达式

TestDelegate d2= (string name) => { Console.WriteLine("你好,{0}!", name); };

d2("Terry");

3.2匿名方法

delegate void TestDelegate(string myName);

TestDelegate d2 = delegate(string name)
{

Console.WriteLine("Hello,{0}!", name);

};

d2(“Test”);

3.3 函数申明

private void DelegateMethod(string name)

{

Console.WriteLine("Hello,{0}!", name);

}

TestDelegate d2 = new TestDelegate(DelegateMethod);

d2(“Test”);

四、使用委托有哪些特点

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

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

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

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

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

五、委托使用场景

委托一般都使用在 Observer模式(观察者模式)。

Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。

Observer模式主要包括如下两类对象:

被监视对象:往往包含着其他对象所感兴趣的内容。

监视者:当对象中的某件事发生的时候,会告知建设者,而建设者则会采取相应的行动。

例如:当你程序处理大批量数据时,需要在程序界面显示进度条进行友好提示,这时你通过委托来实现相当方便。

范例:

public delegate void DelegateMethod(int position, int maxValue);

  public class TestDelegate    {        public DelegateMethod OnDelegate;

public void DoDelegateMethod()
        {
            int maxValue = 100;
            for (int i = 0; i < maxValue; i++)
            {
                if (this.OnDelegate != null)
                {
                    this.OnDelegate(i, maxValue);
                }
            }
        }

TestDelegate test = new TestDelegate();            this.textBox1.Text = "";            this.progressBar1.Value = 0;            test.OnDelegate = new DelegateMethod(delegate(int i, int maxValue)            {                this.textBox1.Text += i.ToString() + Environment.NewLine;                this.progressBar1.Maximum = maxValue;                this.progressBar1.Value++;            });            test.DoDelegateMethod();

六、如何清空委托

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

方法如下:

public class TestDelegate
    {
        public DelegateMethod OnDelegate;

                 public void ClearDelegate()        {            while (this.OnDelegate != null)            {                this.OnDelegate -= this.OnDelegate;            }        }    }
2、如果在类中没有申明清空委托的方法,我们可以利用GetInvocationList查询出委托引用,然后进行去除。

方法如下:

TestDelegate test = new TestDelegate();

if (test.OnDelegate != null)
{
  System.Delegate[] dels = test.OnDelegate.GetInvocationList();
  for (int i = 0; i < dels.Length; i++)
  {
     test.OnDelegate -= dels[i] as DelegateMethod;
  }
}

七、实战范例

功能需求:查询打印机的墨粉量,如果低于50时则发送Email邮件到客户进行提醒。

优化前代码

namespace DelegateExample.Before
{
    public class SpyPrinterToner
    {
        public void CheckPrinterTonerIsLower()
        {
            PhysicalPrinterAction action = new PhysicalPrinterAction();
            int remainToner = action.SelectPrinterToner();
            if (remainToner < 50)
            {
                MessageController controller = new MessageController();
                controller.SendMessage("Printer Name");
            }
        }
    }
 
    public class MessageController
    {
        public void SendMessage(string printerName)
        {
            //TODO: SendMessage
        }
    }
 
    public class PhysicalPrinterAction
    {
        public int SelectPrinterToner()
        {
            return 80;
        }
    }
}

调用:

DelegateExample.Before.SpyPrinterToner toner = new Before.SpyPrinterToner();
            toner.CheckPrinterTonerIsLower();

以上代码也可以说采用了面向对象编程,但是SpyPrinterToner 与 MessageController 之间存在了不必要的耦合度, 造成了日后的程序维护的工作量以及不便于程序的扩展。

那我们该如何降低 SpyPrinterToner 与 MessageController 之间的耦合度,从而达到:高内聚,低耦合的目的。

显而易见我们利用观察者模式可以达到。

优化后的代码

namespace DelegateExample.After
{
 
 
    public class SpyPrinterToner
    {
        public Action<string> OnSendMessage;
 
        public void CheckPrinterTonerIsLower()
        {
            PhysicalPrinterAction action = new PhysicalPrinterAction();
            int remainToner = action.SelectPrinterToner();
            if (remainToner < 50)
            {
                if (this.OnSendMessage != null)
                {
                    this.OnSendMessage("Printer Name");
                }
            }
        }
    }
 
    public class MessageController
    {
        public void SendMessage(string printerName)
        {
            //TODO: SendMessage
        }
    }
 
    public class PhysicalPrinterAction
    {
        public int SelectPrinterToner()
        {
            return 80;
        }
    }
}

调用

DelegateExample.After.SpyPrinterToner toner = new After.SpyPrinterToner();
toner.OnSendMessage += new Action<string>(new After.MessageController().SendMessage);
toner.CheckPrinterTonerIsLower();

进行这样的优化之后,2个类直接的耦合度降低了。

如果日后需求进行了更改,需要增加IM类型的消息或者其他类型的消息类别,那我们则只需要再增加一个委托即可,如果不采用委托去实现,则SpyPrinterToner类又会与IM处理类或者其他类相互耦合。

八、利用Func委托代码优化

在项目开发过程中经常会看到类似的代码:

try
            {
                Do();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
            finally
            {
                DoFinally();
            }

造成代码量的冗余,给日后代码维护带来很多的不便。

有很多种方法可以实现,例如:AOP、委托等。在这里我们主要讲如何利用Func委托来实现代码优化。

private void CallMethod(Func<string> func)
        {
            try
            {
                func();
            }
            catch (Exception ex)
            {
                LogException(ex);
            }
            finally
            {
                DoFinally();
            }
        }

CallMethod(new Func<string>(Do));

我们将方法作为委托进行传入,这样节省了很多的冗余代码。

时间: 2024-08-01 01:14:07

C# 委托应用总结的相关文章

c#系统泛型委托

Action<T> 无返回值的系统泛型委托 namespace ConsoleApp1 { public class UserInfo { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } } class Program { private static List<UserInfo> getInit() { return new List<User

《C#图解教程》读书笔记之五:委托和事件

本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.委托初窥:一个拥有方法的对象 (1)本质:持有一个或多个方法的对象:委托和典型的对象不同,执行委托实际上是执行它所"持有"的方法.如果从C++的角度来理解委托,可以将其理解为一个类型安全的.面向对象的函数指针. (2)如何使用委托? ①声明委托类型(delegate关键字) ②使用该委托类型声明一个委托变量 ③为委托类型增加方法 ④调用委托执行方法 (3)委托的恒定性: 组合委托.为委托+=增加

C# 委托,Lambda表达式,事件

本文章参考sikiC#高级篇,转载请注明出处. 什么是委托 如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托与使用 声明委托有四种方式.一种是原生的,另外三种是C#为了方便给我们封装好的. 四种声明方式分别为delegate, Action, Func, 在C#中使用一个类分为两个阶段,首先定义这个类,告诉编译器这个类由什么字段和方法组成,然后使用这个类实例化对象.在我们使用委托的时候,也需要经过这两个阶段,首先定义委托,告诉编

泛型委托当参数传递

假如有一个Person类: public class Person { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Title { get; set; } } 执行一个方法: /// <summary> /// 传递一个泛型委托方法 /// </summary> /// <param name="acti

类库,委托,is和as运算符,泛型集合

类库:其实就是一堆类文件,只不过用户看不到这些类的源代码,保密性好. 优点:保密性好缺点:如果这个方法不好用,使用者无法自己去更改它. 类文件是.cs    类库是.dll 新建项目为类库,在debug文件夹下找到dll文件 委托:委托可以理解为:函数的指针 关键词:delegate 声明委托类型:public delegate int FirstDel(int a, int b); FirstDel不是类,是委托变量,不能实例化(不能new), 创建委托变量:FirstDel 名字 = 与这个

泛型委托

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 泛型委托 { public delegate int DelCompare<T>(T t1, T t2); // public delegate int DelCompare(object o1, object o2); class Progra

javascript中的事件委托

这几天看到一个面试题,大概就是,让你给1000个li都添加一个click事件,应该怎么添加?大多数人第一开始的感觉可能就是,每个li上边都添加一个呗,那要是这样的话,估计面试的时候就会GG了,这里就是撤出了我们的事件冒泡和捕获机制,以及事件委托机制,对于上边这些,我们慢慢来看. 首先说一下事件冒泡和事件捕获机制,事件冒泡是有微软公司提出来的,事件捕获是有网景公司提出来的,当时两家是争论的不可开交,后来w3c也没办法,就采取了折中的方式,事件产生后先捕获后冒泡, 通常,在js中监听事件的方法共有三

[JS]笔记14之事件委托

-->什么是事件委托-->事件委托原理-->事件委托优点-->事件源 / 目标源 一.什么是事件委托 通俗的讲,onclick,onmouseover,onmouseout等这些就是事件 委托,就是这个事件本来应该加在某些元素上的,而你却加到其他元素上来完成这个事件. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> &

事件委托能够优化js性能

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>面试题练习img居中</title> <style type="text/css"> img { /*display: table-cell; vertical-align: middle;*/ } html,body{ height: 100%; } div{ w

C#高级知识点概要(1) - 委托和事件

作者:linybo 要成为大牛,必然要有扎实的基本功,不然时间再长项目再多也很难有大的提升.本系列讲的C# 高级知识点,是非常值得去撑握的,不仅可以让你写代码时游刃有余,而且去研究和学习一些开源项目时,也不会显得那么吃力了. 希望大家记住,这里讲的所有的知识点,不仅仅是了解了就可以了,还要会灵活用,一定要多思考,撑握其中的编程思想. 本文讲的是委托和事件,这两个词可能你早就耳熟能详,但你是否真正撑握了呢? 本系列讲的C#高级知识点都是要求开发时能达到可以徒手写出来的水平(不依赖搜索引擎.找笔记等