C#学习笔记-委托

委托

  委托类似于C/C++中的函数指针。委托存储对方法的引用,可以按照某些约束指向目标方法,间接地调用这些方法。

// C
#include<stdio.h>

typedef int (*Calc)(int x, int y);

int Add(int x, int y) {
	return x + y;
}

int Sub(int x, int y) {
	return x - y;
}

int main() {
	int x = 100;
	int y = 200;
	int res = 0;

	Calc funcPoint1 = &Add;

	res = funcPoint1(x, y); //间接调用,通过函数指针调用函数
	printf("%d + %d = %d\n", x, y, res);

	res = Sub(x, y); //直接调用,通过函数名调用函数
	printf("%d - %d = %d\n", x, y, res);
}
//C#
class Program
{
    static void Main(string[] args)
    {
        //使用Action委托
        Calculator calculator = new Calculator();
        Action action = new Action(calculator.Report);
        calculator.Report();
        action();

        //使用Func委托
        Func<int, int, int> func1 = new Func<int, int, int>(calculator.Add);
        Func<int, int, int> func2 = new Func<int, int, int>(calculator.Sub);

        Console.WriteLine(func1(1,2));
        Console.WriteLine(func2(1,2));
    }
}

class Calculator
{
    public void Report()
    {
        Console.WriteLine("I have 3 methods.");
    }

    public int Add(int a, int b)
    {
        return a + b;
    }

    public int Sub(int a, int b)
    {
        return a - b;
    }
}

  委托是一种类,所以委托也是一种数据类型。但是和类的声明方式不同,委托的声明格式更像C/C++中函数指针的声明格式。声明的位置应该在名称空间中(在类中声明,委托会变成嵌套类)。

  委托与委托所封装的方法在类型上需要兼容:

  1、返回值的数据类型需一致;

  2、参数列表的个数和数据类型需一致(参数名可不同);

//自定义委托的声明
public delegate double Calc(double x, double y);
class Program
{
    static void Main(string[] args)
    {
        Calculator calculator = new Calculator();
        Calc cal1 = new Calc(calculator.Add);
        Calc cal2 = new Calc(calculator.Sub);
        Calc cal3 = new Calc(calculator.Mul);
        Calc cal4 = new Calc(calculator.Div);

        Console.WriteLine(cal1(1.5, 2));
        Console.WriteLine(cal2(1.5, 2));
        Console.WriteLine(cal3(1.5, 2));
        Console.WriteLine(cal4(1.5, 2));
    }
}

class Calculator
{
    public double Add(double x, double y)
    {
        return x + y;
    }

    public double Sub(double x, double y)
    {
        return x - y;
    }
    public double Mul(double x, double y)
    {
        return x * y;
    }

    public double Div(double x, double y)
    {
        return x / y;
    }
}

委托的一般使用

模板方法,“借用”指定的外部方法来产生结果。

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);
        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();
        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 = "Toy Car";
        return product;

    }
}

回调方法是通过委托类型参数传进主调方法的一个被调用方法,主调方法根据情况调用这个方法。

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);

        Box box1 = wrapFactory.WrapProduct(func1, log);
        Box box2 = wrapFactory.WrapProduct(func2, log);

        Console.WriteLine(box1.Product.Name);
        Console.WriteLine(box2.Product.Name);
    }
}

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
{
    public Box WrapProduct(Func<Product> getProduct, Action<Product> logCallBack)
    {
        Box box = new Box();
        Product product = getProduct();

        if(product.Price >= 50)
        {
            logCallBack(product);
        }
        box.Product = product;
        return box;
    }
}

class ProductFactory
{
    public Product MakePizza()
    {
        Product product = new Product();
        product.Name = "Pizza";
        product.Price = 12;
        return product;
    }

    public Product MakeToyCar()
    {
        Product product = new Product();
        product.Name = "Toy Car";
        product.Price = 100;
        return product;
    }
}

多播委托

  用一个委托封装多个方法。

static void Main(string[] args)
{
    Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
    Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
    Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };

    Action action1 = new Action(stu1.DoHomeWork);
    Action action2 = new Action(stu2.DoHomeWork);
    Action action3 = new Action(stu3.DoHomeWork);
    //执行的顺序按照封装方法的先后顺序 action1 -> action3 -> action 2
    action1 += action3;
    action1 += action2;
    action1();

}
}

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("Student {0} doing homeWork {1} hour(s).", this.ID, i);
            Thread.Sleep(1000);
        }
    }
}

异步调用

class Program
{
    static void Main(string[] args)
    {
        Student stu1 = new Student() { ID = 1, PenColor = ConsoleColor.Yellow };
        Student stu2 = new Student() { ID = 2, PenColor = ConsoleColor.Green };
        Student stu3 = new Student() { ID = 3, PenColor = ConsoleColor.Red };

        //直接同步调用
        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 += action2;
        action1 += action3;
        action1();

        //使用委托实现间接异步调用
        action1.BeginInvoke(null, null);
        action2.BeginInvoke(null, null);
        action3.BeginInvoke(null, null);

        //显式异步调用
        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 task1 = new Task(action1);
        Task task2 = new Task(action2);
        Task task3 = new Task(action3);

        task1.Start();
        task2.Start();
        task3.Start();


        for (int i = 0; i < 10; ++i)
        {
            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine("Main thread {0}.", i);
            Thread.Sleep(1000);
        }
    }
}

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("Student {0} doing homeWork {1} hour(s).", this.ID, i);
            Thread.Sleep(1000);
        }
    }
}

可以使用接口(Interface)取代委托。

class Program
{
    static void Main(string[] args)
    {
        IProductFactory pizzaFactory = new PizzaFactory();
        IProductFactory toyCarFactory = new ToyCarFactory();
        WrapFactory wrapFactory = new WrapFactory();

        Box box1 = wrapFactory.WrapProduct(pizzaFactory);
        Box box2 = wrapFactory.WrapProduct(toyCarFactory);

        Console.WriteLine(box1.Product.Name);
        Console.WriteLine(box2.Product.Name);
    }
}

interface IProductFactory
{
    Product Make();
}

class PizzaFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();
            product.Name = "Pizza";
            return product;
        }
    }

    class ToyCarFactory : IProductFactory
    {
        public Product Make()
        {
            Product product = new Product();
            product.Name = "Toy Car";
            return product;
        }
    }

    class Product
    {
        public string Name { get; set; }
    }

class Box
{
    public Product Product { get; set; }
}


class WrapFactory
{
    public Box WrapProduct(IProductFactory productFactory)
    {
        Box box = new Box();
        Product product = productFactory.Make();
        box.Product = product;
        return box;
    }
}
posted @   owmt  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示