【C#】委托


委托

委托(delegate)是一种类型,定义了一种方法签名,因此可以将方法作为参数进行传递。
委托类似于 C++ 中的函数指针,但比函数指针更加安全和灵活。
使用委托,可以实现事件处理、回调函数等功能。
建议:使用接口取代委托

  • Action
    • 无参无返回
  • Func
    • 有参有返回
        Calaculator calaculator = new Calaculator();
        
        // Action
        new Action(calaculator.Report).Invoke();
        
        // Func
		Func<int, int, int> func1 = new Func<int, int, int>(calaculator.Add);
		Func<int, int, int> func2 = new Func<int, int, int>(calaculator.Sub);
		
		int x = 100;
		int y = 200;
		int z = 0;

		// 可以省略invoke
		z = func1(x, y);
		Console.WriteLine(z);

		z = func2.Invoke(x, y);
		Console.WriteLine(z);

class Calaculator {
    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;
    }
}

自定义委托

// 与类平级,放到类中属于嵌套
public delegate double Calc(double x,double y);
internal class Program
{
    static void Main(string[] args)
    {
        Calaculator calaculator = new Calaculator();
        Calc calc1 = new Calc(calaculator.Add1);
        Calc calc2 = new Calc(calaculator.Mul);

        double x = 100;
        double y = 100;
        double z = 0;
        z = calc1.Invoke(x, y);
        Console.WriteLine(z);
        z = calc2.Invoke(x, y);
        Console.WriteLine(z);
	}
}

模板方法(工厂模式

”借用“指定的外部方法来产生结果 , 提高对代码的复用
ProductFactory() 只需要扩展这个方法,其他方法都不用动

    static void Main(string[] args)
    {
        ProductFactory productFactory = new ProductFactory();
        WrapFactory wrapFactory = new WrapFactory();

        Func<Product> func1 = new Func<Product>(productFactory.MakeToy);
        Func<Product> func2 = new Func<Product>(productFactory.MakePizza);

        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();
        // invoke 执行拿到产品(不用管是什么产品
        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 MakeToy() {
        Product product = new Product();
        product.Name = "Toy";
        return product;
    }
}

回调(callback)函数(观察者模式

调用指定的外部方法
在模板方法基础上添加

internal class Program
{
    static void Main(string[] args)
    {
        ProductFactory productFactory = new ProductFactory();
        WrapFactory wrapFactory = new WrapFactory();

        Func<Product> func1 = new Func<Product>(productFactory.MakeToy);
        Func<Product> func2 = new Func<Product>(productFactory.MakePizza);

        Logger logger = new Logger();
        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);
    }
}

class Logger {
    public void Log(Product product) {
        //DateTime.UtcNow 无时区时间 ; DateTime.Now 有时区
        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.Invoke();

        // 回调函数:触发某种条件就自动执行
        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 MakeToy() {
        Product product = new Product();
        product.Name = "Toy";
        product.Price=120;
        return product;
    }
}

多播(multicast)委托

在这里插入图片描述
在这里插入图片描述

委托的高级使用

1

使用接口 重构 模板方法代码

直接用接口,不使用委托。

方法形参为接口,类继承接口,new不同的类传进同个方法

internal class Program
{
    static void Main(string[] args)
    {
        WrapFactory wrapFactory = new WrapFactory();

        Logger logger = new Logger();
        Action<Product> action = new Action<Product>(logger.Log);

        Box box1 = wrapFactory.WrapProduct(new PizzaFactory());
        Box box2 = wrapFactory.WrapProduct(new 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";
        product.Price = 12;
        return product;
    }
}

class ToyCarFactory : IProductFactory
{
    public Product Make()
    {
        Product product = new Product();
        product.Name = "Toy";
        product.Price = 120;
        return product;
    }
}
class WrapFactory {
    public Box WrapProduct(IProductFactory productFactory) {
        Box box = new Box();
        Product product = productFactory.Make();
        box.Product = product;
        return box;
    }
}
}

注意

委托:
1

参考

刘铁猛——C#

C# 委托是一种类型安全的函数指针,它允许将方法作为参数传递给其他方法,并可以在未知的时间点调用该方法。委托可以封装静态方法或实例方法,在事件处理、回调函数等场景中非常有用。 以下是关于 C# 委托的一些关键特性: 1. **声明**:通过 `delegate` 关键字来定义一个新的委托类型。例如: ```csharp public delegate int MathOperation(int x, int y); ``` 2. **创建和初始化**:可以通过直接指定目标方法名或使用 lambda 表达式来进行委托实例化。如下面的例子所示: - 使用普通方法: ```csharp static int Add(int a, int b) => a + b; // 创建委托并将其绑定到Add方法上 MathOperation operation = new MathOperation(Add); ``` - 或者更简洁地: ```csharp MathOperation addDelegate = (x,y)=>{return x+y;}; ``` 3. **调用**: 直接像调用常规方法一样去调用已赋值过的委托变量即可完成操作。 4. **多播委托**(Multicast Delegates):如果需要让多个接收方响应某个消息,则可以把几个单独的委托合并成一个多播形式;只需简单地对两个现有的委托对象执行加法运算就能实现了。(注意结果还是一个单个的对象) 5. **泛型委托**:为了提高灵活性及复用程度,C# 提供了一些内置的标准泛型委托Action<> 和 Func<>,它们分别用于表示无返回值的操作以及有返回值的功能. 6. **异步支持**:结合async/await语法糖可以让基于委托的任务变得十分方便快捷 7. **匿名方法**,Lambda表达式的引入简化了书写风格. 8. **与事件机制紧密相连** 总之,委托提供了强大的功能使得代码结构更加清晰合理,并且增强了程序设计模式的可能性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值