cstimoty19-委托详解

019 委托 · 语雀C#语言入门详解 委托https://www.yuque.com/yuejiangliu/dotnet/timothy-csharp-019


 

委托相当于cpp中的函数指针

对方法进行间接调用

委托是1个/1组方法的包装器,委托封装方法

一切皆地址

委托为C#所特有,Java对指针的舍弃相当彻底

泛型委托

Action委托无返回值

Func委托有返回值

二者都可以有参数列表

 

cyy声明函数指针:

typedef int(*Calc)(int a,int b);

C#声明委托:

delegate int Calc(int a,int b);

 

 

委托是一种类

1.声明变量;2.创建实例;

需要声明在名称空间内,和类平级,如果声明在类体内,就成为了嵌套类

 

委托的一般使用:把方法当作参数传给另一个方法

委托封装了方法1,在方法2中可以通过委托类型的参数动态调用方法1

1.模板方法

委托有返回值-Func委托

常位于代码中部

2.回调方法callback

委托无返回值-Action委托

常位于代码末尾

Logger类记录程序运行状态,Log方法无返回值

//模板方法
namespace cstimothy191
{
    class Program
    {
        static void Main(string[] args)
        {
            WrapFactory wrapFactory = new WrapFactory();
            ProductFactory productFactory = new ProductFactory();
            //声明委托类型变量,委托封装方法,为后面传参使用
            Func<Product> func1 = new Func<Product>(productFactory.MakePizz);
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
            Box box1 = wrapFactory.WrapProduct(func1);
            Box box2 = wrapFactory.WrapProduct(func2);
            Console.WriteLine(box1.Product.Name);
            Console.WriteLine(box2.Product.Name);
        }
    }
    class Product
    {
        public string Name { get; set; }
    }
    class Box
    {
        public Product Product { get; set; }
    }
    class WrapFactory
    {
        //模板方法
        public Box WrapProduct(Func<Product> getProduct)
        {
            Box box = new Box();
            Product product = getProduct.Invoke();
            box.Product = product;
            return box;
        }
    }
    class ProductFactory
    {
        public Product MakePizz()
        {
            Product product = new Product();
            product.Name = "pizza";
            return product;
        }
        public Product MakeToyCar()
        {
            Product product = new Product();
            product.Name = "toycar";
            return product;
        }
    }
}
//回调方法
namespace cstimothy192
{
    class Program
    {
        static void Main(string[] args)
        {
            WrapFactory wrapFactory = new WrapFactory();
            ProductFactory productFactory = new ProductFactory();
            Func<Product> func1 = new Func<Product>(productFactory.MakePizz);
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
            Logger logger = new Logger();
            Action<Product> log = new Action<Product>(logger.Log);
            Box box1 = wrapFactory.WrapProduct(func1,log);
            Box box2 = wrapFactory.WrapProduct(func2,log);
            Console.WriteLine(box1.Product.Name);
            Console.WriteLine(box2.Product.Name);
        }
    }
    //Logger类记录程序运行状态,Log方法无返回值
    class Logger
    {
        public void Log(Product product)
        {
            //UtcNow无时区
            Console.WriteLine($"{product.Price},{product.Price},{DateTime.UtcNow}");
        }
    }
    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 MakePizz()
        {
            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;
        }
    }
}

使用接口替代委托-代码重构

//使用接口替代委托-代码重构
namespace cstimothy193
{
    class Program
    {
        static void Main(string[] args)
        {
            WrapFactory wrapFactory = new WrapFactory();
            IProductFactory pizzaFactory = new PizzFactory();
            IProductFactory toycarFactory = new ToyCarFactory();
            Logger logger = new Logger();
            Box box1 = wrapFactory.WrapProduct(pizzaFactory,logger);
            Box box2 = wrapFactory.WrapProduct(toycarFactory,logger);
            Console.WriteLine(box1.Product.Name);
            Console.WriteLine(box2.Product.Name);
        }
    }
    class Logger
    {
        public void Log(Product product)
        {
            Console.WriteLine($"{product.Price},{product.Price},{DateTime.UtcNow}");
        }
    }
    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, Logger logger)
        {
            Box box = new Box();
            Product product = productFactory.Make();
            if (product.Price >= 50)
            {
                logger.Log(product);
            }
            box.Product = product;
            return box;
        }
    }
    interface IProductFactory
    {
        Product Make();
    }
    class PizzFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();
            product.Name = "pizza";
            product.Price = 12;
            return product;
        }
    }
    class ToyCarFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();
            product.Name = "toycar";
            product.Price = 100;
            return product;
        }
    }
}

委托是一种方法级别的耦合,违反设计模式

委托使用不当会造成内存泄漏:

委托引用一个方法,如果这个方法是一个实例方法,那这个实例方法必定属于一个对象,如果委托引用了这个实例方法,那么这个对象就必须存在于内存之中,即使没有其他的引用变量引用这个对象,也不能Gc被回收。

 

单播委托-1个委托封装1个方法
多播委托-1个委托封装多个方法
委托相比于接口的应用场景-多播委托
同步调用
直接同步调用
间接同步调用-单播委托,多播委托
using System.Threading;
namespace cstimothy194
{
    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();
            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();
        }
    }
    class Student
    {
        public int ID { get; set; }
        //ConsoleColor-输出时候的颜色
        public ConsoleColor PenColor { get; set; }
        public void DoHomework()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.ForegroundColor = this.PenColor;
                Console.WriteLine($"{this.ID}xxx{i}");
                Thread.Sleep(100);
            }
        }
    }
}

直接间接-方法调用,委托调用

同步异步-单线程,多线程

进程process

线程thread

异步调用的底层机理是多线程

异步调用

隐式异步调用-委托的BeginInvoke

显示异步调用-Thread,Task

//隐式异步调用
using System.Threading;
using System.Threading.Tasks;
namespace cstimothy195
{
    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);
            显示异步调用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();
        }
    }
    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($"{this.ID}xxx{i}");
                Thread.Sleep(100);
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值