博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 委托
阅读量:6366 次
发布时间:2019-06-23

本文共 7910 字,大约阅读时间需要 26 分钟。

一、前言:每次看到委托和事件,心理面总是不自在,原因大家都懂,但是委托和事件在.NET FrameWork里面的应用非常的广泛,所以熟练的掌握委托和事件对一个.NET开发人员来说是十分重要的,所以花半天的时间来彻底的扫下盲点,争取能carry掉!

 

二、概述

1、作用:委托的作用是将方法作为参数传递给方法

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{    class Program    {        static void Main(string[] args)        {               Program p=new Program();            p.SayHello("张三");        }        public void SayHello(string name)        {            ChineseSayHello(name);        }        private void ChineseSayHello(string name)        {            Console.WriteLine("你好:{0}",name);        }    }}

上面的代码主要是一个打招呼程序,当你给SayHello()方法输入参数姓名是,该程序就会吊用中文式的SayHello的方法,但是有一个问题,现在这个程序需要国际化,需要填加其他国家的SayHello()方法,如何美国的,那么这个时候应该加一个language参数,来区分不同的国家,下面是改进后的代码:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{    class SayHello1    {        static void Main(string[] args) {            SayHello1 s1 = new SayHello1();            s1.SayHello("张三", Country.Chinese);            s1.SayHello("张三", Country.America);        }        public void SayHello(string _name, Country _country)        {            switch (_country) {                case Country.America: EnglishSayHello(_name); break;                case Country.Chinese: ChineseSayHello(_name); break;                default: ChineseSayHello(_name); break;            }        }        private void EnglishSayHello(string _name) {            Console.WriteLine("Hello {0}", _name);        }        private void ChineseSayHello(string _name)        {            Console.WriteLine("你好 {0}", _name);        }    }    public enum Country {         //中国        Chinese,        //美国        America    }}

上面的代码通过枚举和switch判断,解决了国际化的问题,但是这样的代码耦合度太高,试想一下,当我们每加一个国家,SayHello()方法就要改变,这是不妥的,话句话说,就是假设我们加一个韩国的SayHello()的方法,在设计层面上来看它仅仅是加了一个韩国的SayHello的方法,但是从代码和角度看,他改变的是整个SayHello()方法的结构,这是不妥的,中国和美国的SayHello方法不应该因为额外加了一个韩国的SayHello方法所出现的安全问题买单。所以这种方法虽然解决了问题,但是产生了不必要的问题,代码的扩展性很差。

下面通过委托来解决上面的问题

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{    //定义一个委托EventHander是微软定义委托的一种标准委托的名字+EventHander    //定义了一个无返回值,参数为name的委托    //注意委托定义的位置和string,delegate,SayHello2的位置是一样的,说明委托也应该是个类型,或者说类    //但是委托的声明方式,却和类不一样。实际上委托最后确实会被编译成一个类.应为delegate是个类,所以任何可以声明类的地方都可以声明委托    public delegate void SayHelloEventHander(string name);    class SayHello2    {        private static void Main(string[] args) {            SayHello2 s2 = new SayHello2();            s2.SayHello("张三", s2.ChineseSayHello);            s2.SayHello("zhangsan", s2.EnglishSayHello);        }        public void SayHello(string _name, SayHelloEventHander _sayHello) {            _sayHello(_name);             }        private void EnglishSayHello(string _name) {            Console.WriteLine("hello:{0}", _name);        }        private void ChineseSayHello(string _name)        {            Console.WriteLine("你好:{0}", _name);        }    }}

 

总结:

<1>委托是一个类,任何可以声明类的地方,都可以声明委托.

<2>委托可以定义方法的类型和返回值

<3>通过使用委托,将方法作为参数传递给方法的方式,减少了程序中if else和switch语句出现的次数,增加了程序的可扩展性

 

2、委托也是一种数据类型

(1)、上面的代码中提到了,可以定义类的地方,就可以定义委托,那么我们就可以推断出,委托实际上也是一种数据类型,我们也可以像申明类一样的方式来申明委托.并调用它;

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{    public class SayHello3    {        public delegate void SayHelloEventHandler(string _name);        static void Main(string[] args)        {            SayHello3 s3 = new SayHello3();            SayHelloEventHandler s1, s2;//定义了两个委托实例            //为实例赋值            s1 = s3.ChineseSayHello;            s2 = s3.EnglishSayHello;            s3.SayHello("张三", s1);            s3.SayHello("张三", s2);        }        public void SayHello(string _name, SayHelloEventHandler sayHello)        {            sayHello(_name);        }        private void ChineseSayHello(string _name)        {            Console.WriteLine("你好:{0}", _name);        }        private void EnglishSayHello(string _name)        {            Console.WriteLine("hello:{0}", _name);        }    }}

 

(2)、将多个方法绑定给同一个委托

这是委托的一个特性:可以将多个方法赋给同一个委托,或者将多个方法绑定给同一个委托,当调用这个委托的时候,讲一次吊用该委托所绑定的方法;代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{    class SayHello5    {        public delegate void SayHelloEventHandler(string _name);        static void Main(string[] args) {            SayHelloEventHandler sr1;            SayHello5 s5 = new SayHello5();            //如果需要给SayHelloEventHandler绑定多个方法,必须先给sr1赋初值,在做+=操作,否则编译器会报错            sr1 = s5.EnglishSayHello;            sr1 += s5.ChineseSayHello;            sr1 -= s5.EnglishSayHello;            sr1 += s5.EnglishSayHello;            s5.SayHello("张三", sr1);        }        public void SayHello(string _name,SayHelloEventHandler sayHello) {            sayHello(_name);        }        private void ChineseSayHello(string _name)        {            Console.WriteLine("你好:{0}", _name);        }        private void EnglishSayHello(string _name)        {            Console.WriteLine("hello:{0}", _name);        }    }}

(3)上面代码中提到了当我们需要给一个委托绑定多个方法是,必须先给第一个赋初值在做+=运算,如果直接+=编译器则会报错。所以这个问题引申出第二种委托定义的方式,代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{    class Thread4    {        public delegate void SayHelloEventHandler(string _name);        static void Main(string[] args)        {            //前面说过委托也是一种类型,他可以向类一样的创建实例            SayHelloEventHander sh = new SayHelloEventHander(ChineseSayHello);//创建了一个SayHelloEventHandler的实例,并给SayHelloEventHandler构造函数赋了初值ChineseSayHello            //然后就可以做+=操作,做后续绑定工作            sh += EnglishHello;        }        private static void ChineseSayHello(string name)        {                    }        private static void EnglishHello(string name)        {        }    }}

 

(4)利用面向对象的方法,封装代码,给上面的代码解耦

分析上面的代码:发现SayHello()这个方法是不变的,那我们就把它封装起来,我们把SayHello的方法封装成SayHelloManager类,外部程序直接通过SayHelloManager类来访问并设置对应的SayHello()方法和参数。

using System;namespace Delegate{    //定义一个无返回值,但是有一个name参数的委托    public delegate void SayHelloEventHandler(string _name);    class SayHello6    {        static void Main(string[] args)        {               //第一种方法            SayHelloManger sm = new SayHelloManger();            sm.SayHelloEventHandler = ChineseSayHello;            sm.SayHelloEventHandler += EnglishSayHello;            sm.SayHello("张三", sm.SayHelloEventHandler);            //第二种调用方式            SayHelloManger sm1 = new SayHelloManger("张三", ChineseSayHello);            sm1.SayHello();            SayHelloManger sm2 = new SayHelloManger("张三",EnglishSayHello);            sm2.SayHello();        }        static void ChineseSayHello(string _name){            Console.WriteLine("你好:{0}", _name);          }        static void EnglishSayHello(string _name){            Console.WriteLine("Hello:{0}", _name);          }    }    //定义一个SayHelloManager类,将所有SayHello()方法需要的参数设置成实例,并给外部调用    public class SayHelloManger    {        public string _name;        public SayHelloEventHandler _sayHelloEventHandler;        public SayHelloEventHandler SayHelloEventHandler        {            get { return _sayHelloEventHandler; }            set { _sayHelloEventHandler = value; }        }        public string Name        {            get { return _name; }            set { _name = value; }        }        public SayHelloManger()        {        }        public SayHelloManger(string _name, SayHelloEventHandler handler)        {            this.SayHelloEventHandler = handler;            this.Name = _name;        }        public void SayHello()        {            this.SayHelloEventHandler(Name);        }        public void SayHello(string _name,SayHelloEventHandler SayHello)        {            SayHello(_name);        }    }}

 

转载地址:http://nwrma.baihongyu.com/

你可能感兴趣的文章
China Unicom and Chunghwa Telecom work together&nb
查看>>
Java图片上查找图片算法
查看>>
Python fabric实现远程操作和部署
查看>>
详解Java中staitc关键字
查看>>
前中情局局长:FBI目的是从根本上改善iPhone
查看>>
大隐隐于市,你身边的那些安全隐患你都知道么?
查看>>
物联网市场迅猛发展 “中国芯”如何把握机会?
查看>>
aws 上使用elb 的多域名问题
查看>>
环球花木网的目标就是致力于打造成为“园林相关行业的专业性门户网站
查看>>
《编写高质量代码:改善c程序代码的125个建议》—— 建议14-1:尽量避免对未知的有符号数执行位操作...
查看>>
《C语言编程魔法书:基于C11标准》——2.2 整数在计算机中的表示
查看>>
全球程序员编程水平排行榜TOP50,中国排名第一
查看>>
HDFS 进化,Hadoop 即将拥抱对象存储?
查看>>
Edge 浏览器奇葩 bug:“123456”打印成“114447”
查看>>
Sirius —— 开源版的 Siri ,由 Google 支持
查看>>
《OpenGL ES应用开发实践指南:Android卷》—— 2.7 小结
查看>>
《Windows Server 2012活动目录管理实践》——第 2 章 部署第一台域控制器2.1 案例任务...
查看>>
Java Date Time 教程-时间测量
查看>>
Selector.wakeup实现注记
查看>>
《Java EE 7精粹》—— 第1章 Java EE 1.1 简介
查看>>