C#学习笔记一 委托、事件
创始人
2024-03-28 07:51:06
0次

C# 委托、事件

在这里插入图片描述

1、Action委托、Func委托

namespace DelegateExample
{class Program{static void main(string[] args){Calculator calculator=new Calculator();//Action委托Action Cal=new Action(calculator.Report);//直接调用函数Calculator.Report();//通过委托调用函数Cal.Invoke();//简便写法Cal();//Func委托int a=100,b=200,c=0;Func func1=new Func(Calculator.Add); //尖括号中为<参数1,参数2,返回值>Func func2=new Func(Calculator.Sub);//利用委托调用函数c=func1.Invoke(a,b);//简便写法 c=func1(a,b)Console.WriteLine(c);c=func2.Invoke(a,b);//简便写法 c=func1(a,b)Console.WriteLine(c);}}class Calculator{public void  Report(){console.WriteLine("123");}public int Add(int a,int b){int result=a+b;return result;}public int Sub(int a,int b){int result=a-b;return result;}}}

2、自定义委托

在这里插入图片描述

避免写错地方结果声明成嵌套类型:

​ 一般委托的声明在命名空间内,和Program类同级,如果声明在Program类中,会声明成为嵌套类 类型。

namespace DelegateExample
{//自定义委托声明格式public delegate double Cal(double x,double y);class Program{static void main(string[] args){Calculator calculator=new Calculator();Cal cal1=new Cal(calculator.Add);Cal cal2=new Cal(calculator.Sub);Cal cal3=new Cal(calculator.Mul);Cal cal4=new Cal(calculator.Div);double a=200,b=100,c=0;c=cal1.invoke(a,b);Console.WriteLine(c);c=cal2.invoke(a,b);Console.WriteLine(c);c=cal3.invoke(a,b);Console.WriteLine(c);c=cal4.invoke(a,b);Console.WriteLine(c);}   }class Calculator{public double Add(double a,double b){return a+b;}public double Sub(double a,double b){return a-b;}public double Mul(double a,double b){return a*b;}public double Div(double a,double b){return a/b;}}}

3、委托的一般使用

在这里插入图片描述

3.1 模板方法

using System;
using System.Collections.Generic;namespace DelegateExample
{class Program{static void Main(string[] args){WrapFactory wrapFactory = new WrapFactory();ProductFactory productFactory = new ProductFactory();Func func1 = new Func(productFactory.MakePizza);Func func2 = new Func(productFactory.MakeToyCar);Box box1 = wrapFactory.WrapProduct(func1);Box box2 = wrapFactory.WrapProduct(func2);Console.WriteLine(box1.Product.Name);Console.WriteLine(box2.Product.Name);Console.ReadKey();}}class Product{public string Name{ get; set; }}class Box{public Product Product { get; set; }}class WrapFactory{public Box WrapProduct(Func getProduct){Product product = getProduct.Invoke();Box box = new Box();box.Product = product;return box;}}class ProductFactory{public Product MakePizza(){Product product = new Product();product.Name = "Pizza";return product;}public Product MakeToyCar(){Product product = new Product();product.Name = "Toy Car";return product;}}}
//使用模板方法的好处,代码复用性高,只需要扩充ProductFactory类中的方法
//Product类、WrapFactory类,均不用修改

3.2 回调方法

需求:

使用委托的回调方法,在上述代码中实现,若产品价格大于等于50时,打印输出商品信息

using System;
using System.Collections.Generic;namespace DelegateExample
{class Program{static void Main(string[] args){WrapFactory wrapFactory = new WrapFactory();ProductFactory productFactory = new ProductFactory();Func func1 = new Func(productFactory.MakePizza);Func func2 = new Func(productFactory.MakeToyCar);Logger logger = new Logger();Action log = new Action(logger.Log);Box box1 = wrapFactory.WrapProduct(func1,log);Box box2 = wrapFactory.WrapProduct(func2,log);Console.WriteLine(box1.Product.Name);Console.WriteLine(box2.Product.Name);Console.ReadKey();}}class Logger{public void Log(Product product){Console.WriteLine("Product '{0}' created at {1}. Price is {2}.", product.Name, DateTime.UtcNow, product.Price);}}class Product{public string Name{ get; set; }public double Price { get; set; }}class Box{public Product Product { get; set; }}class WrapFactory{public Box WrapProduct(Func getProduct,Action logCallback){Product product = getProduct.Invoke();if (product.Price >= 50){logCallback(product);}Box box = new Box();box.Product = product;return box;}}class ProductFactory{public Product MakePizza(){Product product = new Product();product.Name = "Pizza";product.Price = 20;return product;}public Product MakeToyCar(){Product product = new Product();product.Name = "Toy Car";product.Price = 99;return product;}}}

3.3 委托的高级使用

同步与异步的概念:与中文不同

多播委托

using System;
using System.Collections.Generic;
using System.Threading;
namespace DelegateExample 
{class Program{static void Main(string[] args){Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };Student stu2 = new Student() { ID = 1, PenColor = ConsoleColor.Green };Student stu3 = new Student() { ID = 1, PenColor = ConsoleColor.Red };Action action1 = new Action(stu1.DoHomeWork);Action action2 = new Action(stu2.DoHomeWork);Action action3= new Action(stu3.DoHomeWork);//单播委托/*action1.Invoke();action2.Invoke();action3.Invoke();*///多播委托action1 += action2;action1 += action3;action1.Invoke();Console.ReadKey();}}class Student{public int ID { get; set; }public ConsoleColor PenColor { get; set; }public void DoHomeWork(){for (int i = 0; i < 5; i++){Console.ForegroundColor = this.PenColor;Console.WriteLine("Student {0} doing homework {1} hour(s).", this.ID, i);Thread.Sleep(1000);}}}}

隐式异步调用

​ 首先了解一下同步调用

​ 直接同步调用与间接同步调用

using System;
using System.Collections.Generic;
using System.Threading;
namespace DelegateExample 
{class Program{static void Main(string[] args){Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };Student stu2 = new Student() { ID = 1, PenColor = ConsoleColor.Green };Student stu3 = new Student() { ID = 1, PenColor = ConsoleColor.Red };//直接同步调用/*stu1.DoHomeWork();stu2.DoHomeWork();stu3.DoHomeWork();*///间接同步调用Action action1 = new Action(stu1.DoHomeWork);Action action2 = new Action(stu2.DoHomeWork);Action action3 = new Action(stu3.DoHomeWork);action1.Invoke();action2.Invoke();action3.Invoke();//或者使用多播委托,也是同步调用的//action1+=action2;action1+=action3;action1.Invoke();for (int i = 0; i < 10; i++){Console.ForegroundColor = ConsoleColor.Cyan;Console.WriteLine("Main thread {0}.", i);Thread.Sleep(1000);}Console.ReadKey();}}class Student{public int ID { get; set; }public ConsoleColor PenColor { get; set; }public void DoHomeWork(){for (int i = 0; i < 5; i++){Console.ForegroundColor = this.PenColor;Console.WriteLine("Student {0} doing homework {1} hour(s).", this.ID, i);Thread.Sleep(1000);}}}
}

异步调用

​ 隐式异步调用

using System;
using System.Collections.Generic;
using System.Threading;
namespace DelegateExample 
{class Program{static void Main(string[] args){Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };Student stu2 = new Student() { ID = 1, PenColor = ConsoleColor.Green };Student stu3 = new Student() { ID = 1, PenColor = ConsoleColor.Red };//隐式异步调用Action action1 = new Action(stu1.DoHomeWork);Action action2 = new Action(stu2.DoHomeWork);Action action3 = new Action(stu3.DoHomeWork);action1.BeginInvoke(null,null);action2.BeginInvoke(null, null);action3.BeginInvoke(null, null);for (int i = 0; i < 10; i++){Console.ForegroundColor = ConsoleColor.Cyan;Console.WriteLine("Main thread {0}.", i);Thread.Sleep(1000);}Console.ReadKey();}}class Student{public int ID { get; set; }public ConsoleColor PenColor { get; set; }public void DoHomeWork(){for (int i = 0; i < 5; i++){Console.ForegroundColor = this.PenColor;Console.WriteLine("Student {0} doing homework {1} hour(s).", this.ID, i);Thread.Sleep(1000);}}}}

显式异步调用(古老的方式:使用Thread进行显示异步调用)

using System;
using System.Collections.Generic;
using System.Threading;
namespace DelegateExample 
{class Program{static void Main(string[] args){Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };Student stu2 = new Student() { ID = 1, PenColor = ConsoleColor.Green };Student stu3 = new Student() { ID = 1, PenColor = ConsoleColor.Red };/*            Action action1 = new Action(stu1.DoHomeWork);Action action2 = new Action(stu2.DoHomeWork);Action action3 = new Action(stu3.DoHomeWork);//隐式异步调用action1.BeginInvoke(null,null);action2.BeginInvoke(null, null);action3.BeginInvoke(null, null);*///使用Thread进行显式异步调用Thread thread1 = new Thread(new ThreadStart(stu1.DoHomeWork));Thread thread2 = new Thread(new ThreadStart(stu2.DoHomeWork));Thread thread3 = new Thread(new ThreadStart(stu3.DoHomeWork));thread1.Start();thread2.Start();thread3.Start();for (int i = 0; i < 10; i++){Console.ForegroundColor = ConsoleColor.Cyan;Console.WriteLine("Main thread {0}.", i);Thread.Sleep(1000);}Console.ReadKey();}}class Student{public int ID { get; set; }public ConsoleColor PenColor { get; set; }public void DoHomeWork(){for (int i = 0; i < 5; i++){Console.ForegroundColor = this.PenColor;Console.WriteLine("Student {0} doing homework {1} hour(s).", this.ID, i);Thread.Sleep(1000);}}}
}

显式异步调用更高级的方式:Task,需要引用System.Threading.Tasks命名空间

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace DelegateExample 
{class Program{public static object TTask { get; private set; }static void Main(string[] args){Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };Student stu2 = new Student() { ID = 1, PenColor = ConsoleColor.Green };Student stu3 = new Student() { ID = 1, PenColor = ConsoleColor.Red };/*            Action action1 = new Action(stu1.DoHomeWork);Action action2 = new Action(stu2.DoHomeWork);Action action3 = new Action(stu3.DoHomeWork);//隐式异步调用action1.BeginInvoke(null,null);action2.BeginInvoke(null, null);action3.BeginInvoke(null, null);*///使用Thread进行显式异步调用/*Thread thread1 = new Thread(new ThreadStart(stu1.DoHomeWork));Thread thread2 = new Thread(new ThreadStart(stu2.DoHomeWork));Thread thread3 = new Thread(new ThreadStart(stu3.DoHomeWork));thread1.Start();thread2.Start();thread3.Start();*///更高级的方式,使用Task进行显式异步调用Task task1 = new Task(new Action(stu1.DoHomeWork));Task task2 = new Task(new Action(stu2.DoHomeWork));Task task3 = new Task(new Action(stu3.DoHomeWork));task1.Start();task2.Start();task3.Start();for (int i = 0; i < 10; i++){Console.ForegroundColor = ConsoleColor.Cyan;Console.WriteLine("Main thread {0}.", i);Thread.Sleep(1000);}Console.ReadKey();}}class Student{public int ID { get; set; }public ConsoleColor PenColor { get; set; }public void DoHomeWork(){for (int i = 0; i < 5; i++){Console.ForegroundColor = this.PenColor;Console.WriteLine("Student {0} doing homework {1} hour(s).", this.ID, i);Thread.Sleep(1000);}}}
}

最好用接口代替委托

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Mhj2pXf5-1670512875811)(C:\Users\Wu\AppData\Roaming\Typora\typora-user-images\image-20221208185431055.png)]

用接口代替第一个案例中的委托

using System;
using System.Collections.Generic;namespace DelegateExample
{class Program{static void Main(string[] args){IProductFactory pizzaFactory = new PizzaFactory();IProductFactory toyCarFactory = new ToyCarFactory();WrapFactory wrapFactory = new WrapFactory();Box box1 = wrapFactory.WrapProduct(pizzaFactory);Box box2 = wrapFactory.WrapProduct(toyCarFactory);Console.WriteLine(box1.Product.Name);Console.WriteLine(box2.Product.Name);Console.ReadKey();}}interface IProductFactory{Product Make();}class PizzaFactory : IProductFactory{public Product Make(){Product product = new Product();product.Name = "Pizza";return product;}}class ToyCarFactory : IProductFactory{public Product Make(){Product product = new Product();product.Name = "Toy Car";return product;}}class Product{public string Name { get; set; }public double Price { get; set; }}class Box{public Product Product { get; set; }}class WrapFactory{public Box WrapProduct(IProductFactory productFactory){Product product = productFactory.Make();Box box = new Box();box.Product = product;return box;}}
}

事件

1.初步了解

在这里插入图片描述

在这里插入图片描述
统一称为事件的订阅者

在这里插入图片描述
统一称为事件参数

2.动手操作
在这里插入图片描述

1.事件的简单示例

using System;
using System.Timers;
namespace EventExample
{class Program{static void Main(string[] args){Timer timer = new Timer();//timer为事件的拥有者timer.Interval = 1000;Boy boy = new Boy();//boy为事件的订阅者Girl girl = new Girl();timer.Elapsed += boy.Action;timer.Elapsed += girl.Action;timer.Start();Console.ReadLine();}}class Boy{internal void Action(object sender, ElapsedEventArgs e){Console.WriteLine("Jump!");}}class Girl{internal void Action(object sender, ElapsedEventArgs e){Console.WriteLine("Sing!");}}}
  1. 示例2

在这里插入图片描述

using System;
using System.Windows.Forms;namespace EventExample
{class Program{static void Main(string[] args){Form form = new Form();//form是事件的拥有者Controller controller = new Controller(form);//controller是事件的订阅者form.ShowDialog();}}class Controller{private Form form;public Controller(Form form){if (form != null){this.form = form;this.form.Click += this.FormClicked;//form.Click是事件成员,FromClicked是事件处理器}}private void FormClicked(object sender, EventArgs e){this.form.Text = DateTime.Now.ToString();}}
}

3.示例3
在这里插入图片描述

using System;
using System.Windows.Forms;namespace EventExample
{class Program{static void Main(string[] args){MyForm form = new MyForm();//form事件拥有者form.Click += form.FormClicked;//事件成员form.Click;事件处理器form.FormClicked;//事件订阅者也是form;form.ShowDialog();}}class MyForm : Form{internal void FormClicked(object sender, EventArgs e){this.Text = DateTime.Now.ToString();}}
}

4.示例4

using System;
using System.Windows.Forms;namespace EventExample
{class Program{static void Main(string[] args){MyForm form = new MyForm();form.ShowDialog();}}class MyForm : Form{private TextBox textBox;private Button button;//事件拥有者是实例化的 Form.buttonpublic MyForm(){this.textBox = new TextBox();this.button = new Button();this.Controls.Add(this.button);this.Controls.Add(this.textBox);this.button.Click += ButtonClicked;//button.Click是事件成员,//ButtonClicked是事件处理器//事件订阅者是MyForm的实例}private void ButtonClicked(object sender, EventArgs e){this.textBox.Text = "Hello, World!";}}
}

委托、事件

  • C# 委托、事件
    • 1、Action委托、Func委托
    • 2、自定义委托
    • 3、委托的一般使用
      • 3.1 模板方法
      • 3.2 回调方法
      • 3.3 委托的高级使用
        • 同步与异步的概念:与中文不同
        • 多播委托
        • **隐式异步调用**
        • **异步调用**
      • 最好用接口代替委托
  • 事件

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...