自带委托Action Func

Action Func
可用invoke方法,也可以用圆括号代替。
Action返回空值void public void
Func委托
比较delegate Action Func
Action和Func都是基于delegate的特殊用法,Action的返回值类型是void,Func通过泛型可以自定义返回值类型,但型参只能有一种。可以接受0个至16个传入参数,无返回值
Func func1 = new Func(calculator.Add)可以接受0个至16个传入参数,必须具有返回值,Func<输入参数,输出参数> Func>
Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Calculator calculator = new Calculator();
  6. Action action = new Action(calculator.Report);//不需要圆括号
  7. calculator.Report();//直接调用
  8. action.Invoke();//间接调用 委托.invoke()
  9. action();//函数指针写法
  10. Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
  11. Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
  12. int x = 100;
  13. int y = 100;
  14. int z = 0;
  15. z = func1.Invoke(x, y);
  16. z = func1(x,y);//函数指针写法
  17. Console.WriteLine(z);
  18. z = func2.Invoke(x, y);
  19. Console.WriteLine(z);
  20. }
  21. }
  22. class Calculator
  23. {
  24. public void Report()
  25. {
  26. Console.WriteLine("i have 3 methods");
  27. }
  28. public int Add(int a, int b)
  29. {
  30. int result = a + b;
  31. return result;
  32. }
  33. public int Sub(int a, int b)
  34. {
  35. int result = a - b;
  36. return result;
  37. }
  38. }

自定义委托Delegate

委托是一种类型,继承自System.MulticastDelegate多播委托,此类型是特性类型,不能声明类型来继承,只能声明委托来自动继承—编译器限制。
委托 - 图1

  1. public delegate double Calc(int x,int y); //声明
  2. //double目标方法的返回值类型
  3. //int x int y目标方法的参数
  4. //嵌套类写在Program里面,最好加.
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. Calculator calculator = new Calculator();
  10. Calc calc1 = new Calc(calculator.Add);
  11. //传入一个方法给委托Calc,方法的返回类型和参数需要和声明的一致
  12. int x = 4;
  13. int y = 2;
  14. double z = 0;
  15. z = calc1(x, y);
  16. Console.WriteLine(z);
  17. }
  18. }
  19. class Calculator
  20. {
  21. public double Add(int a, int b)
  22. {
  23. double result = a + b;
  24. return result;
  25. }
  26. public double Sub(int a, int b)
  27. {
  28. double result = a - b;
  29. return result;
  30. }
  31. public double Mul(int a, int b)
  32. {
  33. double result = a * b;
  34. return result;
  35. }
  36. public double Div(int a, int b)
  37. {
  38. double result = a / b;
  39. return result;
  40. }
  41. }

委托的一般使用

委托 - 图2

模板方法、回调方法

image.png

  1. public delegate void OpenBoxFood(string ProductName);
  2. class Program
  3. {
  4. static void Main(string[] args)
  5. {
  6. BoxProduct("Pizza",OpenBoxPizza);
  7. BoxProduct("Switch",OpenBoxSwtich);
  8. }
  9. public static void BoxProduct(string productName, OpenBoxFood foodName)
  10. {
  11. foodName(productName);
  12. }
  13. public static void OpenBoxPizza(string productName)
  14. {
  15. Console.WriteLine(productName+" is very delicious!");
  16. }
  17. public static void OpenBoxSwtich(string productName)
  18. {
  19. Console.WriteLine(productName+" is also good!");
  20. }
  21. }
  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. var calculator = new Calculator();
  6. // Action用于无形参无返回值的方法
  7. Action action = new Action(calculator.Report);
  8. calculator.Report();
  9. action();
  10. Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
  11. Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);
  12. int x = 100;
  13. int y = 200;
  14. int z = 0;
  15. z = func1(x, y);
  16. Console.WriteLine(z);
  17. z = func2(x, y);
  18. Console.WriteLine(z);
  19. }
  20. }
  21. class Calculator
  22. {
  23. public void Report()
  24. {
  25. Console.WriteLine("i have three methods");
  26. }
  27. public int Add(int a, int b)
  28. {
  29. return a + b;
  30. }
  31. public int Sub(int a, int b)
  32. {
  33. return a - b;
  34. }
  35. }

委托是一个类型需要创建实例,变量名=new 委托类型名(方法名)

  1. public delegate int Calc_dele(int x ,int y);
  2. class Program
  3. {
  4. static void Main(string[] args)
  5. {
  6. var calculator = new Calculator();
  7. var calc1 = new Calc_dele(calculator.Add); //委托是一个类型需要创建实例,变量名=new 委托类型名(方法名)
  8. Console.WriteLine(calc1(30,80));
  9. }
  10. }
  11. class Calculator
  12. {
  13. public int Add(int a, int b)
  14. {
  15. return a + b;
  16. }
  17. public int Sub(int a, int b)
  18. {
  19. return a - b;
  20. }
  21. public int Mul(int a, int b)
  22. {
  23. return a * b;
  24. }
  25. }
  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. var productFactory = new ProductFactory();
  6. Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
  7. Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
  8. var wrapFactory = new WrapFactory();
  9. Box box1 = wrapFactory.WrapProduct(func1);
  10. Box box2 = wrapFactory.WrapProduct(func2);
  11. Console.WriteLine(box1.Product.Name);
  12. Console.WriteLine(box2.Product.Name);
  13. }
  14. }
  15. class Product
  16. {
  17. public string Name { get; set; } //属性Name
  18. }
  19. class Box
  20. {
  21. public Product Product { get; set; } //属性,Product属于Product类,产品名称
  22. }
  23. class WrapFactory
  24. {
  25. // 模板方法,提高复用性
  26. //包装工厂需要包装产品
  27. //这里的委托类型的参数func 执行了MakePizza()这个方法,
  28. //生产出了一个叫Pizza的产品,然后用盒子把产品包装起来
  29. public Box WrapProduct(Func<Product> getProduct)
  30. {
  31. var box = new Box(); //新建实例box(空盒子)
  32. Product product = getProduct.Invoke(); //第一次调用是MakePizza方法,Make Pizza()方法返回的是Product类型,将Pizza赋给产品名称
  33. box.Product = product; //将产品名称赋给box里面的Product属性,封装起来(包装起来)
  34. return box;//返回盒子
  35. }
  36. }
  37. class ProductFactory
  38. {
  39. public Product MakePizza()
  40. {
  41. var product = new Product();
  42. product.Name = "Pizza";
  43. return product;
  44. }
  45. public Product MakeToyCar()
  46. {
  47. var product = new Product();
  48. product.Name = "Toy Car";
  49. return product;
  50. }
  51. }

委托的高级使用

image.png

单播委托

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. namespace MulitDelegateAlbert
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. Student student1 = new Student() { PenColor = ConsoleColor.Yellow,ID = 1 };
  14. Student student2 = new Student() { PenColor = ConsoleColor.Red, ID = 2};
  15. Student student3 = new Student() { PenColor = ConsoleColor.Green, ID = 3};
  16. Action action = new Action(student1.DoHomework);
  17. Action action1 = new Action(student2.DoHomework);
  18. Action action2 = new Action(student3.DoHomework);
  19. action.Invoke();
  20. action1.Invoke();
  21. action2.Invoke();
  22. }
  23. }
  24. class Student
  25. {
  26. public int ID { get; set; }
  27. public ConsoleColor PenColor { get; set; }
  28. public void DoHomework()
  29. {
  30. for (int i = 0; i < 5; i++)
  31. {
  32. Console.ForegroundColor = this.PenColor;
  33. Console.WriteLine("Student{0} is doing homework for {2} hours by pencolor{1}", ID, PenColor,i);
  34. Thread.Sleep(500);
  35. }
  36. }
  37. }
  38. }

多播委托

一个委托封装多个方法,执行顺序按照封装的顺序来执行。

  1. action += action1;
  2. action += action2;
  3. action.Invoke();

同步与异步(隐式异步调用)

同步调用

  • 直接同步调用 方法名
  • 间接同步调用 委托 代码见上面的单播委托、多播委托 委托.invoke()

异步调用

  • 使用委托进行隐式异步调用 委托.BeginInvoke(null,null) 自动生成分支线程 容易造成资源冲突 ```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;

namespace MulitDelegate { class Program { static void Main(string[] args) { Student student1 = new Student() { ID = 1, PencilColor = ConsoleColor.Red }; Student student2 = new Student() { ID = 2, PencilColor = ConsoleColor.Green }; Student student3 = new Student() { ID = 3, PencilColor = ConsoleColor.Blue };

  1. Action action1 = new Action(student1.DoHomework);
  2. Action action2 = new Action(student2.DoHomework);
  3. Action action3 = new Action(student3.DoHomework);
  4. action1.BeginInvoke(null, null);
  5. action2.BeginInvoke(null, null);
  6. action3.BeginInvoke(null, null);
  7. for (int i = 0; i < 5; i++)
  8. {
  9. Console.ForegroundColor = ConsoleColor.White;
  10. Console.WriteLine("This is Main Thread of {0}",i);
  11. Thread.Sleep(500);
  12. }
  13. Console.Read();
  14. }
  15. }
  16. class Student
  17. {
  18. public int ID { get; set; }
  19. public ConsoleColor PencilColor { get; set; }
  20. public void DoHomework()
  21. {
  22. for (int i = 0; i < 5; i++)
  23. {
  24. Console.ForegroundColor = PencilColor;
  25. Console.WriteLine("Student{0} is doing homework for {1} hours by pencil of {2}",ID,i,PencilColor);
  26. Thread.Sleep(1000);
  27. }
  28. }
  29. }

}

  1. 资源竞争:<br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/957395/1599446458490-abe9324f-f28d-480f-80fe-756125b59953.png#align=left&display=inline&height=312&margin=%5Bobject%20Object%5D&name=image.png&originHeight=351&originWidth=500&size=29107&status=done&style=none&width=445)
  2. - 显示异步调用 Thread古老原始的方式
  3. <a name="nEwut"></a>
  4. ##### Thread:
  5. ```csharp
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Threading;
  11. namespace MulitDelegate
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16. {
  17. Student student1 = new Student() { ID = 1, PencilColor = ConsoleColor.Red };
  18. Student student2 = new Student() { ID = 2, PencilColor = ConsoleColor.Green };
  19. Student student3 = new Student() { ID = 3, PencilColor = ConsoleColor.Blue };
  20. Thread thread1 = new Thread(new ThreadStart(student1.DoHomework));
  21. Thread thread2 = new Thread(new ThreadStart(student2.DoHomework));
  22. Thread thread3 = new Thread(new ThreadStart(student3.DoHomework));
  23. thread1.Start();
  24. thread2.Start();
  25. thread3.Start();
  26. for (int i = 0; i < 5; i++)
  27. {
  28. Console.ForegroundColor = ConsoleColor.White;
  29. Console.WriteLine("This is Main Thread of {0}",i);
  30. Thread.Sleep(500);
  31. }
  32. Console.Read();
  33. }
  34. }
  35. class Student
  36. {
  37. public int ID { get; set; }
  38. public ConsoleColor PencilColor { get; set; }
  39. public void DoHomework()
  40. {
  41. for (int i = 0; i < 5; i++)
  42. {
  43. Console.ForegroundColor = PencilColor;
  44. Console.WriteLine("Student{0} is doing homework for {1} hours by pencil of {2}",ID,i,PencilColor);
  45. Thread.Sleep(1000);
  46. }
  47. }
  48. }
  49. }

Task:

形式一:
Task task1 = new Task(new Action(stu1.DoHomework));
task1.Start();
形式二:
Task task1 = new Task(()=>
{
Action action1 = new Action(stu1.DoHomework);
});
task1.Start();

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. namespace MulitDelegate
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. Student student1 = new Student() { ID = 1, PencilColor = ConsoleColor.Red };
  14. Student student2 = new Student() { ID = 2, PencilColor = ConsoleColor.Green };
  15. Student student3 = new Student() { ID = 3, PencilColor = ConsoleColor.Blue };
  16. Task task1 = new Task(new Action(student1.DoHomework));
  17. Task task2 = new Task(new Action(student2.DoHomework));
  18. Task task3 = new Task(new Action(student3.DoHomework));
  19. task1.Start();
  20. task3.Start();
  21. try
  22. {
  23. Task task = new Task(() =>
  24. {
  25. Action action = new Action(student1.DoHomework);
  26. });
  27. }
  28. catch (Exception)
  29. {
  30. throw;
  31. }
  32. Task task4 = new Task(() =>
  33. {
  34. student2.DoHomework();
  35. });
  36. Task task5 = new Task(() =>
  37. {
  38. student3.DoHomework();
  39. });
  40. task4.Start();
  41. for (int i = 0; i < 5; i++)
  42. {
  43. Console.ForegroundColor = ConsoleColor.White;
  44. Console.WriteLine("This is Main Thread of {0}",i);
  45. Thread.Sleep(500);
  46. }
  47. Console.Read();
  48. }
  49. }
  50. class Student
  51. {
  52. public int ID { get; set; }
  53. public ConsoleColor PencilColor { get; set; }
  54. public void DoHomework()
  55. {
  56. for (int i = 0; i < 5; i++)
  57. {
  58. Console.ForegroundColor = PencilColor;
  59. Console.WriteLine("Student{0} is doing homework for {1} hours by pencil of {2}",ID,i,PencilColor);
  60. Thread.Sleep(1000);
  61. }
  62. }
  63. }
  64. }

设计模式

使用接口(Interface)取代一些对委托的使用:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. namespace MulitDelegate
  8. {
  9. class Program
  10. {
  11. static void Main(string[] args)
  12. {
  13. IProductFactory pizzaFactory = new PizzaFactory();
  14. IProductFactory toycarFactory = new ToyCarFactory();
  15. var wrapFactory = new WrapFactory();
  16. Box box1 = wrapFactory.WrapProduct(pizzaFactory);
  17. Box box2 = wrapFactory.WrapProduct(toycarFactory);
  18. Console.WriteLine(box1.Product.Name);
  19. Console.WriteLine(box2.Product.Name);
  20. Console.ReadLine();
  21. }
  22. }
  23. interface IProductFactory
  24. {
  25. Product Make();
  26. }
  27. class PizzaFactory : IProductFactory
  28. {
  29. public Product Make()
  30. {
  31. var product = new Product();
  32. product.Name = "Pizza";
  33. return product;
  34. }
  35. }
  36. class ToyCarFactory : IProductFactory
  37. {
  38. public Product Make()
  39. {
  40. var product = new Product();
  41. product.Name = "Toy Car";
  42. return product;
  43. }
  44. }
  45. class Product
  46. {
  47. public string Name { get; set; } //属性Name
  48. }
  49. class Box
  50. {
  51. public Product Product { get; set; } //属性,Product属于Product类,产品名称
  52. }
  53. class WrapFactory
  54. {
  55. // 模板方法,提高复用性
  56. //包装工厂需要包装产品
  57. //这里的委托类型的参数func 执行了MakePizza()这个方法,
  58. //生产出了一个叫Pizza的产品,然后用盒子把产品包装起来
  59. public Box WrapProduct(IProductFactory productFactory)
  60. {
  61. var box = new Box(); //新建实例box(空盒子)
  62. Product product = productFactory.Make(); //第一次调用是MakePizza方法,Make Pizza()方法返回的是Product类型,将Pizza赋给产品名称
  63. box.Product = product; //将产品名称赋给box里面的Product属性,封装起来(包装起来)
  64. return box;//返回盒子
  65. }
  66. }
  67. }