几行代码搞懂C#中的委托

源码链接: 码云

1 什么是委托

这个名词困惑了了我好久,应该对比C++中的函数指针(一个指向函数的指针),理解了函数指针就理解委托了.
函数指针的就是一个指针变量指向函数,例子如下,定义了一个*pf的函数指针,入参是两个int,返回值也是int,将pf的地址指向max函数,这样pf也能使用max函数.

//函数实例

//定义函数
int max(int a,int b){
    return a>b?a;b;
}	

//定义函数指针
int (*pf)(int, int);	

//指针指向函数
pf = max;

//使用函数指针
int result = pf(1,5);

2 函数指针与委托的区别

C# 中的委托与 C++ 中的函数指针在概念上有相似之处,都是用来引用函数或方法的。然而,它们在实际使用和安全性上有很大的不同。C# 的委托是完全面向对象的,提供了更高的安全性和易用性。

以下是 C# 委托与 C++ 函数指针之间的一些主要区别:

安全性

  1. 类型安全:C# 的委托是类型安全的,意味着它们只能引用具有特定签名(返回类型和参数列表)的方法。尝试将不匹配的方法赋值给委托会导致编译错误。而 C++ 的函数指针在类型安全方面较为宽松,可能导致运行时错误。

  2. 内存管理:在 C# 中,委托由垃圾回收器(Garbage Collector)自动管理,这减少了内存泄漏的风险。而在 C++ 中,使用函数指针时需要手动管理内存,如果不当处理可能导致内存泄漏或其他问题。

面向对象特性

  1. 封装对象实例和方法:C# 的委托可以封装对象实例和方法,这意味着它们可以引用实例方法或静态方法。当委托被调用时,它会自动处理对象实例的绑定和方法的调用。相比之下,C++ 的函数指针只引用函数,不涉及对象实例。

  2. 多播和事件:C# 的委托支持多播(即一个委托可以引用多个方法),并且可以与事件一起使用,提供了一种发布-订阅机制。而 C++ 的函数指针通常只引用单个函数,不支持多播或事件机制。

便捷性

  1. Lambda 表达式和匿名方法:C# 允许使用 Lambda 表达式和匿名方法来创建委托实例,这使得编写简短且灵活的代码变得容易。而 C++ 则没有类似的特性。

  2. 委托链和返回值处理:在 C# 中,当委托引用多个方法时,可以定义这些方法的调用顺序(链式调用),并且可以处理返回值(例如,通过最后一个调用的方法返回结果)。而在 C++ 中,函数指针通常只引用单个函数,返回值处理需要手动进行。

总结: 虽然 C# 的委托和 C++ 的函数指针在概念上相似,但它们在安全性、面向对象特性和便捷性方面存在显著差异。C# 的委托提供了更高级别的抽象和安全性,使得在 C# 中使用函数引用变得更加简单、安全和灵活。

3 如何使用委托

1 声明委托

委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同标签的方法。

//委托可以在类外声明,该委托的引用方法入参是string,返回值是void
public delegate void Callback(string message);

public class MyDelegateClass
{
    //委托也可以在类内声明,该委托的引用方法入参是两个int,返回值也是int
    public delegate int InternalDelegate(int a,int b);
}

2 实例化委托

Callback callback = MethodClass.WriteMessage;//实例化委托,并绑定方法

3 使用委托

callback("sunny老师,你好");

4 使用Lambda表达式创建委托的实例

{//有入参无出参,委托实例用lambda表达式实例化
    Callback callback = (s) =>
    {
        Console.WriteLine($"传递进来的参数是{s}");
    };
    callback("keson");
}

{//有入参有出参,委托实例用lambda表达式实例化
    MyDelegateClass myDelegateClass = new MyDelegateClass();
    MyDelegateClass.MaxValueDelegate HandlerMaxValue = (a, b) =>
    {
        return a > b ? a : b;
    };
    int result = HandlerMaxValue(5, 13);
    Console.WriteLine(result);
}

5 多播委托

多播委托(Multicast Delegate)是委托的一个特性,它允许将多个方法关联到同一个委托实例上,并可以在一次调用中执行所有关联的方法。多播委托是通过使用 += 运算符将方法添加到委托实例中,或使用 -= 运算符从委托实例中移除方法来实现的。当委托被调用时,所有添加到该委托的方法都会按照它们被添加的顺序依次执行。

Callback callback = MethodClass.WriteMessage;//添加第一个方法
callback += MethodClass.PrintMessage;//添加第二个方法
callback("sunny老师,你好");

6 回调函数

将委托作为参数传递,同时在其他方法中使用该委托.

{//回调函数:将委托作为参数进行传递
    Callback callback = MethodClass.WriteMessage;//实例化委托
    MethodClass.MethodWithCallback(4, 7, callback);//将委托作为参数传递
}

public static void MethodWithCallback(int param1, int param2, Callback callback)
{
	callback("The number is: " + (param1 + param2).ToString());//在方法中使用委托
}

7 完整代码

  • 方法类
  public class MethodClass
   {
       public static void WriteMessage(string message)
       {
           Console.WriteLine($"方法一的信息是:{message}");
       }

       public static void PrintMessage(string message)
       {
           Console.WriteLine($"方法二的信息是:{message}");
       }

       public static int MaxValue(int a, int b)
       {
           return a > b ? a : b;
       }

       public static void MethodWithCallback(int param1, int param2, Callback callback)
       {
           callback("The number is: " + (param1 + param2).ToString());
       }
   }
  • 委托类
//委托类
    //委托可以在类外声明,该委托的引用方法入参是string,返回值是void
    public delegate void Callback(string message);
    public class MyDelegateClass
    {
        //委托也可以在类内声明,该委托的引用方法入参是两个int,返回值也是int
        public delegate int MaxValueDelegate(int a,int b);
    }
  • 主函数
 //主函数
{//如何使用类内委托
    //实例化委托类
    MyDelegateClass myDelegateClass = new MyDelegateClass();
    // 实例化委托
    MyDelegateClass.MaxValueDelegate HandlerMaxValue = MethodClass.MaxValue;
    //使用委托调用方法
    int result = HandlerMaxValue(1, 56);
    Console.WriteLine(result);
}

{//如何使用类外的委托
    Callback callback = MethodClass.WriteMessage;
    callback("sunny老师,你好");
}

{//实例化委托的另外一写法
    Callback callback = new Callback(MethodClass.WriteMessage);
    callback("sunny老师回复,同学们好呀"!);
}

{//回调函数:将委托作为参数进行传递
    Callback callback = MethodClass.WriteMessage;
    MethodClass.MethodWithCallback(4, 7, callback);
}

{//有入参无出参,委托实例用lambda表达式实例化
    Callback callback = (s) =>
    {
        Console.WriteLine($"传递进来的参数是{s}");
    };
    callback("keson");
}

{//有入参有出参,委托实例用lambda表达式实例化
    MyDelegateClass myDelegateClass = new MyDelegateClass();
    MyDelegateClass.MaxValueDelegate HandlerMaxValue = (a, b) =>
    {
        return a > b ? a : b;
    };
    int result = HandlerMaxValue(5, 13);
    Console.WriteLine(result);
}

{//委托的多播
    Callback callback = MethodClass.WriteMessage;//添加第一个方法
    callback += MethodClass.PrintMessage;//添加第二个方法
    callback("sunny老师,你好");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值