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值在发生改变!");
}