委託代碼詳解
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<int, int, int> func = new Func<int, int, int>(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<int> pre1 = new Predicate<int>(myDate.Is29);
result = pre1(2020); //或result = pre1.Invoke(2020);
Console.WriteLine("閏年:" + result);
Predicate<DateTime> pre2 = new Predicate<DateTime>(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 = value;
}
}
}
static void Main(string[] args)
{
EventTest et = new EventTest();
et.ValueChanged += new EventTest.MyEventHandler(myEventFunction);
et.Value = 100;
et.Value = 200;
}
public static void myEventFunction()
{
Console.WriteLine("value值在發生改變!");
}