委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。C# 中的委托(Delegate)类似于 C 或 C++ 中函数的指针。本文主要介绍C# 委托(delegate)。

1、委托

委托(delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生自 System.Delegate 类。委托是一种引用类型,虽然在定义委托时与方法有些相似,但不能将其称为方法。委托的使用包括定义声明委托、实例化委托以及调用委托。委托在使用时遵循三步走的原则,即定义声明委托、实例化委托以及调用委托。

2、委托声明

委托声明定义委托能引用的的方法,委托声明定义了引用的方法的参数和返回值的类型。

语法:

delegate <return type> <delegate-name> <parameter list>

例如,

public delegate int MyDelegate (string str);

注意:上面示例代码中,int定义的是引用方法的返回值类型,string str定义的是引用方法的参数

3、委托的使用

委托声明之后,声明的委托类型使用时,也需要使用new关键字来创建对象,并且可以与一个方法关联,

例如,

public delegate void FileDelegate(string str);
FileDelegate fileRead = new FileDelegate(ReadFile);
FileDelegate fileWrite = new FileDelegate(WriteFile);

例如,

using System;
delegate int Calc(int a,int b);
namespace MyDelegate
{
   class DelegateDemo
   {
      public static int Add(int a,int b)
      {
         return a+b;
      }
      public static int Minus(int a,int b)
      {
         return a-b;
      }
      public static int Mult(int a,int b)
      {
         return a*b;
      }
      static void Main(string[] args)
      {
         // 创建委托实例
         Calc c1 = new Calc(Add);
         Calc c2 = new Calc(Minus);
         Calc c3 = new Calc(Mult);
         // 使用委托对象调用方法
         Console.WriteLine("{0}", c1(8,2));
         Console.WriteLine("{0}", c2(8,2));
         Console.WriteLine("{0}", c3(8,2));
      }
   }
}

4、委托的多播

多播委托是指在一个委托中注册多个方法,在注册方法时可以在委托中使用加号运算符或者减号运算符来实现添加或撤销方法。创建一个委托被调用时要调用的方法的调用列表。这被称为委托的 多播(multicasting),也叫组播。

例如,

using System;
delegate int Calc(int a,int b);
namespace MyDelegate
{
   class DelegateDemo
   {
      public static int Add(int a,int b)
      {
         Console.WriteLine(a + b);
         return a+b;
      }
      public static int Minus(int a,int b)
      {
         Console.WriteLine(a - b);
         return a-b;
      }
      public static int Mult(int a,int b)
      {
         Console.WriteLine(a * b);
         return a*b;
      }
      static void Main(string[] args)
      {
         // 创建委托实例
         Calc c;
         Calc c1 = new Calc(Add);
         Calc c2 = new Calc(Minus);
         Calc c3 = new Calc(Mult);
         c = c1;
         c += c2;
         c += c3;
         // 使用委托对象调用方法
         Console.WriteLine("{0}", c(8,2));//三个方法都执行了,返回的是最一个值
      }
   }
}

5、匿名委托

匿名委托是指使用匿名方法注册在委托上,实际上是在委托中通过定义代码块来实现委托的作用。

语法:

委托名 委托对象 = delegate
{
    //代码块
};

例如,

using System;
delegate int Calc(int a,int b);
namespace MyDelegate
{
   class DelegateDemo
   {
      static void Main(string[] args)
      {
         // 创建委托实例
         Calc c;
         Calc c1 = delegate(int a,int b)
        {
            Console.WriteLine(a + b);
            return a+b;
        };
         Calc c2 = delegate(int a,int b)
        {
            Console.WriteLine(a - b);
            return a-b;
        };
         Calc c3 = delegate(int a,int b)
        {
            Console.WriteLine(a * b);
            return a*b;
        };
         c = c1;
         c += c2;
         c += c3;
         // 使用委托对象调用方法
         Console.WriteLine("{0}", c(4,2));//多播三个方法都执行了,返回的是最一个值
      }
   }
}

6、使用内置委托

 C# 中,ActionFuncPredicate 是非常常用的 内置委托(delegate)类型,它们是为了简化委托声明而引入的泛型类型,常用于 LINQ、回调、事件处理、函数式编程等场景。

常用的委托类型:

类型参数返回类型
Action任意void
Func<T>任意T
Predicate<T>1个bool

例如,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Action<string> greet = name => 
            Console.WriteLine("Hi, " + name);
            greet("Alice"); // 输出:Hi, Alice
            
            Func<int, int, int> sum = (a, b) => a + b;
            Console.WriteLine(sum(2, 3)); // 输出:5
            
            Predicate<int> isEven = x => x % 2 == 0;
            Console.WriteLine(isEven(4)); // 输出:True

            Console.ReadKey();
        }
    }
}