C#入门详解(10)

匿名 (未验证) 提交于 2019-12-02 23:40:02

什么是委托

委托是函数指针的升级版

实例:C/C++中的函数指针

一切皆地址

变量(数据)是以莫个地址为起点的一段内存中所存储的值

函数(算法)是以莫个地址为七点的一段内存中所存储的一组机器语言指令

直接调用与间接调用

直接调用:通过函数名来调用函数,CPU是通过函数名来直接获取函数所在的地址并开始执行-》返回

间接调用:通过函数指针来调用函数,CPU通过读取函数指针存储的值来获得函数所在地址并开始执行-》返回

委托的简单使用

Action委托

Func委托

委托的声明

委托是一种类,类是数据类型,所以委托也是一种数据类型

它的声明方式与一般类不同,主要是为了照顾可读性

注意声明委托的位置

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

委托与所封装的方法必须类型兼容

返回值的数据类型一致

参数列表在个数和数据类型上一致(参数名不需要一样)

委托的使用

实例:把方法当作参数传给另一个方法

正确使用1:模板方法:借用指定的外部方法来产生结果

相当于填空题

常位于代码中部

委托有返回值

正确使用2:回调方法:调用制定的外部方法

相当于流水线

常位于代码尾部

委托无返回值

注意:难精通+易使用+功能强大的东西,一旦被滥用则后果非常严重

缺点1:这是一种方法级别的紧耦合,现实工作中要慎之又慎

缺点2:使可读性下降,debug的难度增加

缺点3:把委托回调,异步调用和多线程纠缠在一起,会让代码变得难以阅读和维护

缺点4:委托使用不当有可能造成内存泄漏和程序性能下降

实例代码

模板方法:

声明三个类,分别是产品类,盒子类,包装类

 class Product     {         public string Name { get; set; }     }      class Box     {         public Product Product { get; set; }     }      class WarpBox     {         public Box GetProduct(Func<Product> func)         {             Box box = new Box();             box.Product = func.Invoke();             return box;         }     }

声明产品工厂类并实现包装盒子类中得Func类型委托

 class ProductFactory     {         public Product MakePizaa()         {             Product product = new Product();             product.Name = "Pizaa";             return product;         }         public Product MakeToyCar()         {             Product product = new Product();             product.Name = "ToyCar";             return product;         }     }

直接调用产品工厂类中的方法

 static void Main(string[] args)         {             ProductFactory factory = new ProductFactory();             WarpBox warpbox = new WarpBox();             Box box1 = warpbox.GetProduct(factory.MakePizaa);             Box box2 = warpbox.GetProduct(factory.MakeToyCar);             Product product1 = box1.Product;             Product product2 = box2.Product;             Console.WriteLine(product1.Name);             Console.WriteLine(product2.Name);             Console.ReadLine();         }   

回调方法:

增加日志类

    class Logger     {         public void MakeLog(Product product)         {                 Console.WriteLine(string.Format("产品名{0},它的价格为{1},生产时间为{2}", product.Name, product.Price,DateTime.UtcNow));         }     }

在产品工厂里添加action委托类型参数

 class WarpBox     {         public Box GetProduct(Func<Product> func,Action<Product> action)         {             Box box = new Box();             box.Product = func.Invoke();             if (box.Product.Price>=50)             {                 action.Invoke(box.Product);             }                          return box;         }     }

调用

 static void Main(string[] args)         {             ProductFactory factory = new ProductFactory();             WarpBox warpbox = new WarpBox();             Logger logger = new Logger();             Box box1 = warpbox.GetProduct(factory.MakePizaa,logger.MakeLog);             Box box2 = warpbox.GetProduct(factory.MakeToyCar,logger.MakeLog);             Product product1 = box1.Product;             Product product2 = box2.Product;             Console.WriteLine(product1.Name);             Console.WriteLine(product2.Name);             Console.ReadLine();         }   

委托的高级使用

多播委托

    class Program     {         static void Main(string[] args)         {             Student stu1 = new Student { Id = 1, PenColor = ConsoleColor.Cyan };             Student stu2 = new Student { Id = 2, PenColor = ConsoleColor.Red };             Student stu3 = new Student { Id = 3, PenColor = ConsoleColor.Yellow };             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 < 4; i++)             {                 Console.ForegroundColor = this.PenColor;                 Console.WriteLine(string.Format("{0} do homework", this.Id));                 Thread.Sleep(1000);             }         }     }

隐式异步调用

基础概念:

同步:你昨完了我接着做

异步:我们同时做

每个运行的程序是一个进程

每个进程可以拥有多个线程

差异:

同步调用是在一个线程下

异步调用的机理是在多个线程下

隐式多线程/显示多线程

直接同步调用:使用方法名

间接同步调用:使用单播/多播委托invoke方法

隐式异步调用:使用BeginInvoke方法

显示异步调用:使用Thread或Task

应该适时地使用接口取代一些对委托的使用

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!