C#进阶-委托(Delegrate)

2024-02-03 10:35:21 浏览数 (1)

类似于 C 或 C 中函数的指针,委托是C#的函数指针,是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。本篇文章我们将讲解C#里委托的类型及如何使用。委托的语法第一次接触难免感到陌生,最好的学习方式就是在项目中多去使用,相信会有很多感悟。

委托

① 声明和实例化委托

委托声明决定了可由该委托引用的方法。委托可指向一个与其具有相同参数和返回值(或一样没有参数或返回值)的方法。

代码语言:javascript复制
修饰符 delegate 返回值类型 委托名(参数列表); //声明委托
委托名  委托对象名 = new 委托名(方法名); //实例化委托
代码语言:javascript复制
namespace Delegrate
{
  /*也可以在namespace里声明委托*/
  //public delegate void FuncDelegrate(); 
  //public delegate string FuncDelegrateString(string x);

  class Program
  {
    /*声明委托*/
    public delegate void FuncDelegrate(); //无参无返回值委托
    public delegate string FuncDelegrateString(string x);//有参有返回值委托

    static void Main(string[] args)
    {
      /*实例化委托*/
      FuncDelegrate funcDelegrateA = new FuncDelegrate(Hello);
      funcDelegrateA();
      FuncDelegrateString funcDelegrateB = new FuncDelegrateString(Hello);
      funcDelegrateB("xxx");
    }

    public static void Hello()
    {
      Console.WriteLine("Hello");
    }

    public static string Hello(string x)
    {
      Console.WriteLine("Hello,"   x);
      return "Hello";
    }

  }
} 
代码语言:javascript复制
/*输出结果*/
Hello
Hello,xxx

② 委托数组

委托数组存储相同委托的方法,可以通过遍历数组依次执行里面委托的方法。

代码语言:javascript复制
委托名[] 委托对象名 = {委托的方法1, 委托的方法2, ...}; 
代码语言:javascript复制
namespace Delegrate
{
  class Program
  {
    /*声明委托*/
    public delegate void FuncDelegrate(); //无参无返回值委托
    public delegate string FuncDelegrateString(string x);//有参有返回值委托

    static void Main(string[] args)
    {
      //无参数无返回值委托数组
      FuncDelegrate[] funcArrayA = { Hello, World };
      foreach (FuncDelegrate func in funcArrayA)
      {
        func();
      }

      //带参数带返回值的委托的数组
      FuncDelegrateString[] funcArrayB = { Hello, World };
      foreach (FuncDelegrateString func in funcArrayB)
      {
        FuncAry(func, "Damon");
      }
    }

    public static void FuncAry(FuncDelegrateString func, string value)
    {
      Console.WriteLine("");
      Console.WriteLine("方法"   GetFunctionName(func)   "返回值是"   func(value));
     }

    public static void Hello()
    {
      Console.WriteLine("Hello");
    }

    public static void World()
    {
      Console.WriteLine("World");
    }

    public static string Hello(string x)
    {
       Console.WriteLine("Hello,"   x);
       return "Hello";
    }

    public static string World(string x)
    {
       Console.WriteLine(x   "'s World");
       return x;
    }

  }
} 
代码语言:javascript复制
/*输出结果*/
Hello
World
Hello,Damon方法Hello返回值是Hello
Damon's World方法World返回值是Damon

③ Action和Func

Action和Func都是.NET Framework内置的泛型委托,免声明直接实例化调用。

代码语言:javascript复制
/* Action是.NET Framework内置的泛型委托,要求委托必须无返回值 */
Action<参数类型> 委托对象名 = 方法名 //有参情况
Action 委托对象名 = 方法名 //无参情况
代码语言:javascript复制
/* Func是.NET Framework内置的泛型委托,支持有参有返回值 */
Func <返回类型> 委托对象名 = 方法名
Func <参数, 返回类型> 委托对象名 = 方法名
Func <参数, 参数, 返回类型> 委托对象名 = 方法名 //更多参数同理
代码语言:javascript复制
namespace Delegrate
{
  class Program
  {
    /*声明委托*/
    public delegate void FuncDelegrate(); //无参无返回值委托
    public delegate string FuncDelegrateString(string x);//有参有返回值委托

    static void Main(string[] args)
    {
      //Action是.NET Framework内置的泛型委托,要求委托必须无返回值
      /* Action<参数类型> 委托对象名 = 方法名 */
      Action[] actions = { Hello, World };
      foreach (Action func in actions)
      {
        func();
      }

      //Func是.NET Framework内置的泛型委托,支持有参有返回值
      //Func <返回类型> 委托对象名 = 方法名
      Func<int> func1 = ReturnIntValue;

      //Func <参数, 返回类型> 委托对象名 = 方法名
      Func<int, string> func2 = World;

      //Func <参数, 参数, 返回类型> 委托对象名 = 方法名(更多参数同理)
      Func<string, string, string> func3 = World;

      Func<int, string>[] funcArrayC = { Hello, World };
      foreach (Func<int, string> func in funcArrayC)
      {
        FuncAry(func, 114514);
      }
    }

    public static void FuncAry(FuncDelegrateString func, string value)
    {
      Console.WriteLine("");
      Console.WriteLine("方法"   GetFunctionName(func)   "返回值是"   func(value));
     }

    public static void Hello()
    {
      Console.WriteLine("Hello");
    }

    public static void World()
    {
      Console.WriteLine("World");
    }

    public static string Hello(string x)
    {
       Console.WriteLine("Hello,"   x);
       return "Hello";
    }

    public static string World(string x)
    {
       Console.WriteLine(x   "'s World");
       return x;
    }

    public static string World(int x)
    {
      Console.WriteLine(x   "'s World");
      return "World(int x)";
    }

    public static int ReturnIntValue()
    {
      return 1;
    }
  }
} 
代码语言:javascript复制
/*输出结果*/
Hello
World
Hello,114514
方法Hello返回值是Hello(int x)
114514's World
方法World返回值是World(int x)

④ 匿名委托

代码语言:javascript复制
//这里的Func和delegate都是系统自带不需要声明
Func<T> 委托对象名 = delegate(方法参数){ 
  方法体

};
代码语言:javascript复制
namespace Delegrate
{
  class Program
  {
    static void Main(string[] args)
    {
      //匿名方法
      /* Func<T> 委托对象名 = delegate(方法参数){ 方法体 }; */
      Func<int, string> AnonymousDelegate = delegate (int x)
      {
        return "1";
      };
    }
  }
} 

⑤ 委托的多播

委托对象可使用 “ ” 运算符进行合并相同类型的委托,也可使用 “-” 运算符移除任一合并委托中的委托。一个合并委托调用它所合并的N个委托。在实际工作中,我们常常创建一个委托被调用时要调用的方法的调用列表。

代码语言:javascript复制
委托名  委托对象A;
委托名  委托对象B = new 委托名(方法名);
委托名  委托对象C = new 委托名(方法名);
委托对象A = 委托对象B;
委托对象A  = 委托对象C;
委托对象A -= 委托对象C;
代码语言:javascript复制
namespace Delegrate
{
  class Program
  {
    /*声明委托*/
    public delegate void FuncDelegrate(); //无参无返回值委托
    public delegate string FuncDelegrateString(string x);//有参有返回值委托

    static void Main(string[] args)
    {
      //委托的多播
      FuncDelegrateString fds;
      FuncDelegrateString fds1 = new FuncDelegrateString(Hello);
      FuncDelegrateString fds2 = new FuncDelegrateString(World);
      fds = fds1;
      fds  = fds2;//表示在委托列表里添加
      //fds -= fds2;//表示从委托列表里去除
      fds("Damon");

      //第二种写法
      FuncDelegrate fb1 = new FuncDelegrate(StaticFeedbackFunc);//这里直接调用的静态方法
      Program p = new Program();
      FuncDelegrate fb2 = new FuncDelegrate(p.FeedbackFunc);//非静态方法需要实例化调用
      FuncDelegrate fbChain = null;
      fbChain = (FuncDelegrate)Delegate.Combine(fbChain, fb1);//和 =一样
      fbChain = (FuncDelegrate)Delegate.Combine(fbChain, fb2);
      fbChain = (FuncDelegrate)Delegate.Remove(fbChain, new FuncDelegrate(p.FeedbackFunc));//和-=一样
    }

    public static string Hello(string x)
    {
       Console.WriteLine("Hello,"   x);
       return "Hello";
    }

    public static string World(string x)
    {
       Console.WriteLine(x   "'s World");
       return x;
    }

   public static void StaticFeedbackFunc()
   {
     Console.WriteLine("StaticFeedbackFunc()");
   }

   public void FeedbackFunc()
   {
      Console.WriteLine("FeedbackFunc()");
    }
  }
} 
代码语言:javascript复制
/*输出结果*/
Hello,Damon
Damon's World
StaticFeedbackFunc()

⑥ 事件

事件(Event)是类或者对象向其他类或对象通知发送的事情的一种特殊签名的委托。事件使用event关键词来声明,他的返回值是一个委托类型。

代码语言:javascript复制
public event 委托类型 事件名;
代码语言:javascript复制
namespace Delegrate
{
  /*声明委托*/
  public delegate void FuncDelegrate(); //无参无返回值委托

  class Program
  {
    static void Main(string[] args)
    {
      //事件
      /* public event 委托类型 事件名; */
      DelegrateEvent delegrateEvent = new DelegrateEvent();
      delegrateEvent.DelegateEvent  = Hello;//类似
      delegrateEvent.DelegateEvent  = World;
      delegrateEvent.DelegateEvent -= World;
    }

    public static void Hello()
    {
      Console.WriteLine("Hello");
    }

    public static void World()
    {
      Console.WriteLine("World");
    }
  }
  
  class DelegrateEvent
  {
    //声明委托,event可以让外部无法直接访问这个委托
    public event FuncDelegrate DelegateEvent = null;
  }
} 

0 人点赞