zoukankan      html  css  js  c++  java
  • C#重点内容之:委托(delegate)

    起源

    在C语言中,一个函数名代表的是一个地址。比如,创建一个函数int add(int x,int y),此时的函数名add等同于函数地址,调用方法:add(2,4)。这一点没有什么讨论的。

    随着typeof的使用,可以使用一个函数指针,typeof int(*P)(int,int),它表示一个函数指针类型,该指针指向两个形参,返回值为int的函数形式。此时P为一个类型,调用它等价于add

    比如P p=&add;

    p(20,30),相当于等价调用add

    ——————————————————

    看到上面的例子,直觉的想到,能不能把这个函数指针类型放到形参中,这样就可以执行不同的操作。比如:

    int Calc(P p,int x,int y){

      p(x,y);

    }

    此时的P是很空泛的概念,只要符合函数指针类型的函数都可以进来,比如加减乘除等各种方法都可以适配,也就是说,用一个方法Calc可以执行各种运算,在这里p可以看作一个方法。在这里,我们看明白了,这些转化的操作就是想把方法放到形参中

    如果我们熟练JS(也可以说是函数式编程语言),JS中函数是一等公民,把函数作为形参是非常平常的事情。(注:关于委托,还会在C++相关笔记中进行记录)

    为了记忆方便,提取了重点。

    委托类似于指针,可以理解为函数指针的升级版,这是理解委托最关键的地方。

    Action和Func

    系统自带的两种委托:

    • Action
    • Func

    Action型委托要求委托的目标方法没有返回值,但是可以有形参

    Action  action=new Action(目标方法);

    Func型委托要求委托的目标方法可以带有返回值和形参,形如:

    Func<T1,T2,T3> func1=new Func<T1,T2,T3>(目标方法);

    * 其中,T1为返回类型,T2、T3表示形参类型

    自定义委托delegate的声明

    • 委托是一种类(class),类是数据类型所以委托也是一种数据类型
    • 它的声名方式与一般的类不同,主要是为了照顾可读性和C/C++传统
    • 注意声明委托的位置,避免写错地方结果声明成嵌套类型
    • delegate   double   Calc    (double x,double y);

    可以与C语言函数指针类比:typedef void(*p)(int,int);

    委托的一般使用

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

    • 正确使用:模板方法,“借用”指定的外部方法来产生结果
    • 正确使用2:回调方法(callback),调用指定的外部方法

    模板方法

    结论:

    模板方法的作用在于复用。

    完整代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DelegateExample
    {
        class Program
        {
            static void Main(string[] args)
            {
                ProductFactory productFactory = new ProductFactory();
                WrapFactory wrapFactory = new WrapFactory();
    
                Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
                Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
                Box box1 = wrapFactory.WrapProduct(func1);
                Box box2 = wrapFactory.WrapProduct(func2);
    
                Console.WriteLine(box1.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 MakePizza()
                {
                    Product product = new Product();
                    product.Name = "Pizza";
                    return product;
                }
                public Product MakeToyCar()
                {
                    Product product = new Product();
                    product.Name = "ToyCar";
                    return product;
                }
            }
        }
    }
    View Code

    回调方法

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace DelegateExample
    {
        class Program
        {
            static void Main(string[] args)
            {
                ProductFactory productFactory = new ProductFactory();
                WrapFactory wrapFactory = new WrapFactory();
    
                Func<Product> func1 = new Func<Product>(productFactory.MakePizza);
                Func<Product> func2 = new Func<Product>(productFactory.MakeToyCar);
    
                Logger logger = new Logger();
                Action<Product> log = new Action<Product>(logger.Log); //Log的委托;
    
                Box box1 = wrapFactory.WrapProduct(func1, log);
                Box box2 = wrapFactory.WrapProduct(func2, log);
    
                Console.WriteLine(box1.Product.Name);
    
            }
            class Product //产品类
            {
                public string Name { get; set; }
                public double Price { get; set; }
            }
            class Box //盒子类
            {
                public Product Product { get; set; }
            }
            class Logger
            {
                public void Log(Product product)
                {
                    Console.WriteLine(product.Price);
                }
            }
            class WrapFactory  //包装工厂
            {
                public Box WrapProduct(Func<Product> getProduct, Action<Product> logCallback)
                {
                    Box box = new Box();
                    Product product = getProduct.Invoke();
                    if (product.Price > 50) //如果产品价格大于50,就执行回调方法;
                    {
                        logCallback(product);
                    }
                    box.Product = product;
                    return box;
                }
            }
            class ProductFactory  //产品工厂
            {
                public Product MakePizza()
                {
                    Product product = new Product();
                    product.Name = "Pizza";
                    product.Price = 30;
                    return product;
                }
                public Product MakeToyCar()
                {
                    Product product = new Product();
                    product.Name = "ToyCar";
                    product.Price = 100;
                    return product;
                }
            }
        }
    }
    View Code
  • 相关阅读:
    [SDOI2009]HH的项链
    [PA2010]Riddle
    纪念品
    [Code+#4]最短路
    [JSOI2007]文本生成器
    绝世好题
    一个输入框提示列表效果
    iGOOGLE分栏
    获取图片地址然后显示在input中
    网页配色工具。
  • 原文地址:https://www.cnblogs.com/tinaluo/p/7341729.html
Copyright © 2011-2022 走看看