与2021-12-22-《C#基础+WinForms》-内容总结-P11 委托+Lambda配合食用
回溯:2022/01/11/12/13
一、P19内容总结
二、什么是委托delegate
//C#中已经声明好的委托类型举例
//Action委托与Func委托
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
//Action委托指向的是参数列表为空,返回值为void的方法
Action action = new Action(calculator.Report);
//直接调用
calculator.Report();
//间接调用1
action.Invoke();
//间接调用2
action();
/*Func<>委托指向的是有参数、有返回值的方法
Func<参数,参数,返回值>*/
Func<int, int, int> func1 = new Func<int,int,int>(calculator.Add);
Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
int x = 100;
int y = 200;
int z = 0;
//间接调用1
z = func1.Invoke(x, y);
Console.WriteLine(z);
z = func2.Invoke(x, y);
Console.WriteLine(z);
//间接调用2
z = func1(x, y);
Console.WriteLine(z);
z = func2(x, y);
Console.WriteLine(z);
}
}
//有一个Calculator类有三种方法
class Calculator
{
public void Report()
{
Console.WriteLine("I have 3 methods.");
}
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;
}
}
三、委托的声明[自定义委托]
//声明返回值为double类型,参数列表为double类型的委托
public delegate double Calc(double x, double y);
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
Calc calc1 = new Calc(calculator.Add);
Calc calc2 = new Calc(calculator.Sub);
Calc calc3 = new Calc(calculator.Mul);
Calc calc4 = new Calc(calculator.Div);
double x = 100;
double y = 200;
double z = 0;
//间接调用1
z = calc1.Invoke(x, y);
Console.WriteLine(z);
z = calc2.Invoke(x, y);
Console.WriteLine(z);
z = calc3.Invoke(x, y);
Console.WriteLine(z);
z = calc4.Invoke(x, y);
Console.WriteLine(z);
//间接调用2
z = calc1(x, y);
Console.WriteLine(z);
z = calc2(x, y);
Console.WriteLine(z);
z = calc3(x, y);
Console.WriteLine(z);
z = calc4(x, y);
Console.WriteLine(z);
}
}
class Calculator
{
public double Add(double a,double b)
{
double result = a + b;
return result;
}
public double Sub(double a, double b)
{
double result = a - b;
return result;
}
public double Mul(double a, double b)
{
double result = a * b;
return result;
}
public double Div(double a, double b)
{
double result = a / b;
return result;
}
}
四、委托的使用
委托的一般使用
class Program
{
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();
//准备委托类型的参数,传入方法模板
Func<Product> fun1 = new Func<Product>(productFactory.MakePizza);
Func<Product> fun2 = new Func<Product>(productFactory.MakeToyCar);
//包装产品
Box box1 = wrapFactory.WrapProduct(fun1);
Box box2 = wrapFactory.WrapProduct(fun2);
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);
}
}
class Product
{
public string Name { get; set; }
}
class Box
{
//每个包装箱具有一个Product类型的属性--箱子里包装的产品
public Product Product { get; set; }
}
//把产品包上盒子交给用户
class WrapFactory
{
//模板方法:传入一个名字,把名字放在box里打包,返回打包后的box
public Box WrapProduct(Func<Product>getProduct)
{
Box box = new Box();
Product product = getProduct.Invoke();
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 = "ToyCar";
return product;
}
}
2)回调方法callback,调用指定的外部方法
class Program
{
static void Main(string[] args)
{
ProductFactory productFactory = new ProductFactory();
WrapFactory wrapFactory = new WrapFactory();
//准备委托类型的参数,传入方法模板
Func<Product> fun1 = new Func<Product>(productFactory.MakePizza);
Func<Product> fun2 = new Func<Product>(productFactory.MakeToyCar);
Logger logger = new Logger();
Action<Product> log = new Action<Product>(logger.Log);
//包装产品
Box box1 = wrapFactory.WrapProduct(fun1,log);
Box box2 = wrapFactory.WrapProduct(fun2,log);
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);
}
}
//记录程序的运行状态,没有返回值
class Logger
{
public void Log(Product product)
{
Console.WriteLine("Produce '{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<Product>getProduct,Action<Product> logCallback)
{
Box box = new Box();
Product product = getProduct.Invoke();
if(product.Price>=50)
{
logCallback(product);
}
box.Product = product;
return box;
}
}
//生产各种产品
class ProductFactory
{
public Product MakePizza()
{
Product product = new Product();
product.Name = "Pizza";
product.Price = 12;
return product;
}
public Product MakeToyCar()
{
Product product = new Product();
product.Name = "ToyCar";
product.Price = 100;
return product;
}
}
委托的高级使用
//单播委托:一个委托内封装一个方法
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
Action action1 = new Action(stu1.DoHomework);
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1.Invoke();
action2.Invoke();
action3.Invoke();
}
}
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);
}
}
}
//多播委托:一个委托内封装的不只是一个方法
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor = ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
Action action1 = new Action(stu1.DoHomework);
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1 += action2;
action1 += action3;
action1.Invoke();
}
}
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);
}
}
}
同步调用 举例:直接同步调用、间接同步调用 (单播、多播)
注意:“间接–直接”和“同步–异步”两个概念
//直接同步调用
//用方法的名字调用该方法
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
//直接调用三个方法,然后主线程还有一些事情要做
stu1.DoHomework();
stu2.DoHomework();
stu3.DoHomework();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread {0}.", i);
Thread.Sleep(1000);
}
}
}
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);
}
}
}
//间接同步调用(单播委托)
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
Action action1 = new Action(stu1.DoHomework);
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1.Invoke();
action2.Invoke();
action3.Invoke();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread {0}.", i);
Thread.Sleep(1000);
}
}
}
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);
}
}
}
//间接同步调用(多播委托)
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
Action action1 = new Action(stu1.DoHomework);
Action action2 = new Action(stu2.DoHomework);
Action action3 = new Action(stu3.DoHomework);
action1+=action2;
action1+=action3;
action1.Invoke();
for (int i = 0; i < 10; i++)
{
Console.WriteLine("Main thread {0}.", i);
Thread.Sleep(1000);
}
}
}
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);
}
}
}
异步调用 隐式多线程&显示多线程
隐式异步调用 BeginInvoke方法
记住:隐式多线程的BeginInvoke方法
若编译程序发生异常
提示:Operation is not supported on this platform.
原因:创建的是.NET Core项目,但是在.NET Core中不支持Action.BeginInvoke(null, null)的委托异步调用方法。
解决办法:重新创建一个.NET Framework项目,把代码重新复制过去后,就没有异常了。
//隐式多线程
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1, PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
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.WriteLine("Main thread {0}.", i);
Thread.Sleep(1000);
}
}
}
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
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
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.WriteLine("Main thread {0}.", i);
Thread.Sleep(1000);
}
}
}
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
class Program
{
static void Main(string[] args)
{
Student stu1 = new Student() { ID = 1,PenColor=ConsoleColor.Red };
Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Blue };
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.WriteLine("Main thread {0}.", i);
Thread.Sleep(1000);
}
}
}
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.Reflection;
using Microsoft.Extensions.DependencyInjection;
using System.Threading;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
PizzaFactory pizzaFactory = new PizzaFactory();
CarToyFactory carToyFactory = new CarToyFactory();
WrapFactory wrapFactory = new WrapFactory();
//包装产品
Box box1 = wrapFactory.WrapProduct(pizzaFactory);
Box box2 = wrapFactory.WrapProduct(carToyFactory);
Console.WriteLine(box1.Product.Name);
Console.WriteLine(box2.Product.Name);
}
}
class Product
{
public string Name { get; set; }
}
interface IProductFactory
{
Product Made();
}
class PizzaFactory : IProductFactory
{
public Product Made()
{
Product product = new Product();
product.Name = "Pizza";
return product;
}
}
class CarToyFactory : IProductFactory
{
public Product Made()
{
Product product = new Product();
product.Name = "ToyCar";
return product;
}
}
class Box
{
//每个包装箱具有一个Product类型的属性--箱子里包装的产品
public Product Product { get; set; }
}
//把产品包上盒子交给用户
class WrapFactory
{
//模板方法:传入一个名字,把名字放在box里打包,返回打包后的box
public Box WrapProduct(IProductFactory productFactory)
{
Box box = new Box();
Product product = productFactory.Made();
box.Product = product;
return box;
}
}
}