C# 委托类型的理解

rui-ren / 2023-08-21 / 原文



namespace ConsoleApp820
{
    internal class Program
    {
        static void Main(string[] args)
        {
            ProductFactory productFactory = new ProductFactory();
            WrapFactory wrapFactory = new WrapFactory();
            //如果要委托的是一个有返回值的方法,必须选func,如果返回值void,那么要选Action委托
            
            //Func的尖括号中,如果只放一个类型,那么这个类型是他的返回值类型
            //如果放了多个类型,那么前面的都是他的传入类型,最后一个是会返回的类型
            //而Action的尖括号中,由于返回值一定是void,所以放的都是传入类型

            //准备一个委托类型的变量,把变量当参数传入模板方法
            //现在这个func1就是一个方法了
            //func1是一个会返回Product类型的方法
            //而不是一个普通的变量
            Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
            Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);


            Logger logger = new Logger();
            //准备一个action委托的变量,传入这个委托的是Product变量
            //现在action这个变量是一个需要传入Product类型的方法
            //而不是一个普通的变量
            Action<Product> action = new Action<Product>(logger.Log);
            
            
            //希望最终返回箱子,可以查看箱子中的物品
            //使用委托,间接调用包装产品这个类来查看箱子
            Box box1 = wrapFactory.WrapProduct(func1, action);
            Box box2 = wrapFactory.WrapProduct(func2, action);
            Console.WriteLine(box1.Product.Name);
            Console.WriteLine(box2.Product.Name);
        }
    }
    //logger回调方法,只有需要/执行到这个方法之后,才会执行
    //否则在整个程序的生命周期,都不会执行这个方法
    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
    {
        //模板方法,这个方法接收一个委托类型的参数
        //一般的方法都是接受比如int类型的参数
        //这个Func委托封装的方法,会返回一个product类型的对象

        //一般的方法括号内是(int x)这种类型+形参
        //但这个方法括号内是(委托类型+方法作为形参)
        //这样我就可以打破以往只能传入普通类型的桎梏,传入一个经过委托封装的方法
        //委托允许我们引用一个方法,就像引用一个变量一样。
        //委托特别重要,因为它使得我们能够在运行时动态地绑定方法。
        public Box WrapProduct(Func<Product> getProduct,Action<Product> logcallback)

        {
            Box box = new Box();
            //传进来的getproduct方法在这里
            //如下面的类,这个方法会返回产品名,传给箱子中的产品
            Product product = getProduct();
            //第二个通过委托传进来的是回调方法
            //如果产品价格>=50才会被执行
            //需要给此方法传入一个产品实例
            if (product.Price >= 50)
            {
                logcallback(product);
            }

            box.Product = product;
            return box;
        }
    }
    //产品工厂类,方法会返回产品名
    class ProductFactory
    {
        public Product MakePizza()
        {
            //类型 实例变量 = new 类
            Product product = new Product();
            //产品实例的名字是pizza
            product.Name = "Pizza";
            product.Price = 20;
            //方法返回这个类型的实例
            return product;
        }
        public Product MakeToyCar()
        {
            Product product = new Product();
            product.Name = "ToyCar";
            product.Price = 120;
            return product;
        }
    }
}

C