委托代码详解

C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。
委托(Delegate) 是存有对某个方法的引用的一种引用类型变量 。
现实世界中的委托:
【委托代码详解】自己动手模式:
委托代码详解
文章图片

委托模式:一种类型的委托
委托代码详解
文章图片

委托模式:多种类型的委托
委托代码详解
文章图片

一、C#内置委托 (1)Action委托:用于调用无参数,无返回值的函数。

class OASystem { public void WelComeChinese() { Console.WriteLine("您好,欢迎来到******系统!"); } public void WelComeEnglish() { Console.WriteLine("Hello, welcome to the ****** system!"); } }

static void Main(string[] args) { //直接调用 //OASystem oa = new OASystem(); //oa.WelComeChinese(); //oa.WelComeEnglish(); //委托调用 OASystem oa = new OASystem(); Action action1 = new Action(oa.WelComeChinese); Action action2 = new Action(oa.WelComeEnglish); action1(); //或action1.Invoke(); action2(); //或action2.Invoke(); }

(2)Func委托:一种泛型委托,Func有一系列的重载。
class Calculator { public int Add(int a, int b) { return a + b; } public int Sub(int a, int b) { return a - b; } public int Mul(int a, int b) { return a * b; } public int Div(int a, int b) { return a / b; } }

static void Main(string[] args) { //直接调用任意一种运算 //Calculator cal = new Calculator(); //int result = cal.Add(1, 2); //Console.WriteLine(result); Calculator cal = new Calculator(); Func func = new Func(cal.Add); int result = func(1, 2); //或func.Invoke(1, 2); Console.WriteLine(result); }

(3)Predicate:一个传入参数,返回值为bool。
class MyDate { //判断年份是否是闰年 public bool Is29(int year) { if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) return true; else return false; } //判断是否需要工作(星期一到星期五需要工作,周六周日不需要) public bool IsWork(DateTime date) { if ((int)date.DayOfWeek == 0 || (int)date.DayOfWeek == 6) return false; else return true; } }

static void Main(string[] args) { //直接调用两个方法 //bool result = false; //MyDate myDate = new MyDate(); //result = myDate.Is29(2020); //Console.WriteLine("闰年:"+result); //result = myDate.IsWork(new DateTime(2020, 7, 3)); //Console.WriteLine("工作:"+result); //委托调用两个方法 bool result = false; MyDate myDate = new MyDate(); Predicate pre1 = new Predicate(myDate.Is29); result = pre1(2020); //或result = pre1.Invoke(2020); Console.WriteLine("闰年:" + result); Predicate pre2 = new Predicate(myDate.IsWork); result = pre2(new DateTime(2020, 7, 3)); //或result = pre2.Invoke(new DateTime(2020, 7, 3)); Console.WriteLine("工作:" + result); }

二、自定义委托及委托的多播(组播)
class Calculator { public int Num { get; set; } public void Add(int n) { this.Num += n; } public void Sub(int n) { this.Num -= n; } public void Mul(int n) { this.Num *= n; } public void Div(int n) { this.Num /= n; } }

delegate void ChangeNum(int n); class Program { static void Main(string[] args) { //自定义委托调用函数方法 //Calculator cal = new Calculator(); //cal.Num = 100; //ChangeNum cnAdd = new ChangeNum(cal.Add); //cnAdd(10); //Console.WriteLine(cal.Num); //委托的多播(组播) //相同类型的委托被合并,可以创建一个委托被调用时要调用的方法的调用列表 Calculator cal = new Calculator(); cal.Num = 100; ChangeNum cnAdd = new ChangeNum(cal.Add); ChangeNum cnSub = new ChangeNum(cal.Sub); ChangeNum cnMul = new ChangeNum(cal.Mul); ChangeNum cnDiv = new ChangeNum(cal.Div); ChangeNum cn = cnAdd; cn += cnMul; cn += cnSub; cn(50); Console.WriteLine(cal.Num); } }

三、委托作为参数传递 手机类:
class Phone//手机 { public string Name { get; set; }//手机名字 }

包装盒类:
class Box//包装盒 { public Phone MyPhone { get; set; } //手机 }

手机生产工厂类:
class PhoneFactory { public Phone MakeXiaoMi() { Phone phone = new Phone(); phone.Name = "小米手机"; return phone; } public Phone MakeHuawei() { Phone phone = new Phone(); phone.Name = "华为手机"; return phone; } }

包装生产工厂类:
delegate Phone MakePhone(); class WrapFactory { #region 为每种手机进行包装盒工作-常规写法 //包装小米手机 public Box WarpXiaoMi() { PhoneFactory phoneFactory = new PhoneFactory(); Phone phone = phoneFactory.MakeXiaoMi(); Box box = new Box(); box.MyPhone = phone; return box; } //包装华为手机 public Box WarpHuawei() { PhoneFactory phoneFactory = new PhoneFactory(); Phone phone = phoneFactory.MakeHuawei(); Box box = new Box(); box.MyPhone = phone; return box; } #endregion#region 将委托作为参数 public Box WarpPhone(MakePhone mp) { Phone phone = mp(); Box box = new Box(); box.MyPhone = phone; return box; } #endregion }

Main函数:
static void Main(string[] args) { #region 生产并包装两个手机-常规写法 //WrapFactory wrapFactory = new WrapFactory(); //Box box1 = wrapFactory.WarpXiaoMi(); //Console.WriteLine(box1.MyPhone.Name + "生产及包装已经完成!"); //Box box2 = wrapFactory.WarpHuawei(); //Console.WriteLine(box2.MyPhone.Name + "生产及包装已经完成!"); #endregion#region 生产并包装两个手机-委托作为参数 PhoneFactory phoneFactory = new PhoneFactory(); MakePhone makeXiaomi = new MakePhone(phoneFactory.MakeXiaoMi); MakePhone makeHuawei = new MakePhone(phoneFactory.MakeHuawei); WrapFactory wrapFactory = new WrapFactory(); Box box1 = wrapFactory.WarpPhone(makeXiaomi); Console.WriteLine(box1.MyPhone.Name + "生产及包装已经完成!"); Box box2 = wrapFactory.WarpPhone(makeHuawei); Console.WriteLine(box2.MyPhone.Name + "生产及包装已经完成!"); #endregion }

四、利用委托实现匿名函数回调
delegate void CallBackDelegate(int score); class Student { public string Name { get; set; } //姓名 public string Mail { get; set; } //邮箱 public int Score { get; set; } //分数 public void Exam(CallBackDelegate callback = null) { Console.WriteLine("请填写姓名:"); this.Name = Console.ReadLine(); Console.WriteLine("请填写邮箱:"); this.Mail = Console.ReadLine(); Random rnd = new Random(); this.Score = rnd.Next(0, 101); Console.WriteLine("该学生面试成绩为:" + this.Score); if (callback != null) callback(this.Score); } }

static void Main(string[] args) { //Student stu = new Student(); //CallBackDelegate myDelegate = delegate (int score) //{ //if (score >= 60) //Console.WriteLine("已经给" + stu.Name + "的邮箱:" //+ stu.Mail + "发送了录用入职邀请!"); //else //Console.WriteLine("很遗憾,我们不能录用您!"); //}; //stu.Exam(); //无参数调用 //stu.Exam(myDelegate); //有参数调用Student stu = new Student(); //stu.Exam(); //或 stu.Exam((score) => { if (score >= 60) Console.WriteLine("已经给" + stu.Name + "的邮箱:" + stu.Mail + "发送了录用入职邀请!"); else Console.WriteLine("很遗憾,我们不能录用您!"); }); }

五、委托与事件
class EventTest { public delegate void MyEventHandler(); public event MyEventHandler ValueChanged; private int value; public int Value { get { return value; } set { ValueChanged(); this.value = https://www.it610.com/article/value; } } }

static void Main(string[] args) { EventTest et = new EventTest(); et.ValueChanged += new EventTest.MyEventHandler(myEventFunction); et.Value = https://www.it610.com/article/100; et.Value = 200; } public static voidmyEventFunction() { Console.WriteLine("value值在发生改变!"); }

    推荐阅读