C#进阶-委托(Delegrate)

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

委托

一、声明和实例化委托

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

修饰符delegate返回值类型委托名(参数列表); //声明委托委托名委托对象名=new委托名(方法名); //实例化委托
namespaceDelegrate{
/*也可以在namespace里声明委托*///public delegate void FuncDelegrate(); //public delegate string FuncDelegrateString(string x);classProgram  {
/*声明委托*/publicdelegatevoidFuncDelegrate(); //无参无返回值委托publicdelegatestringFuncDelegrateString(stringx);//有参有返回值委托staticvoidMain(string[] args)
    {
/*实例化委托*/FuncDelegratefuncDelegrateA=newFuncDelegrate(Hello);
funcDelegrateA();
FuncDelegrateStringfuncDelegrateB=newFuncDelegrateString(Hello);
funcDelegrateB("xxx");
    }
publicstaticvoidHello()
    {
Console.WriteLine("Hello");
    }
publicstaticstringHello(stringx)
    {
Console.WriteLine("Hello,"+x);
return"Hello";
    }
  }
}
/*输出结果*/HelloHello,xxx

二、委托数组

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

委托名[] 委托对象名= {委托的方法1, 委托的方法2, ...}
namespaceDelegrate{
classProgram  {
/*声明委托*/publicdelegatevoidFuncDelegrate(); //无参无返回值委托publicdelegatestringFuncDelegrateString(stringx);//有参有返回值委托staticvoidMain(string[] args)
    {
//无参数无返回值委托数组FuncDelegrate[] funcArrayA= { Hello, World };
foreach (FuncDelegratefuncinfuncArrayA)
      {
func();
      }
//带参数带返回值的委托的数组FuncDelegrateString[] funcArrayB= { Hello, World };
foreach (FuncDelegrateStringfuncinfuncArrayB)
      {
FuncAry(func, "Damon");
      }
    }
publicstaticvoidFuncAry(FuncDelegrateStringfunc, stringvalue)
    {
Console.WriteLine("");
Console.WriteLine("方法"+GetFunctionName(func) +"返回值是"+func(value));
     }
publicstaticvoidHello()
    {
Console.WriteLine("Hello");
    }
publicstaticvoidWorld()
    {
Console.WriteLine("World");
    }
publicstaticstringHello(stringx)
    {
Console.WriteLine("Hello,"+x);
return"Hello";
    }
publicstaticstringWorld(stringx)
    {
Console.WriteLine(x+"'s World");
returnx;
    }
  }
}
/*输出结果*/HelloWorldHello,Damon方法Hello返回值是HelloDamon's World方法World返回值是Damon

三、Action和Func

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

/* Action是.NET Framework内置的泛型委托,要求委托必须无返回值 */Action<参数类型>委托对象名=方法名//有参情况Action委托对象名=方法名//无参情况
/* Func是.NET Framework内置的泛型委托,支持有参有返回值 */Func<返回类型>委托对象名=方法名Func<参数, 返回类型>委托对象名=方法名Func<参数, 参数, 返回类型>委托对象名=方法名//更多参数同理
namespaceDelegrate{
classProgram  {
/*声明委托*/publicdelegatevoidFuncDelegrate(); //无参无返回值委托publicdelegatestringFuncDelegrateString(stringx);//有参有返回值委托staticvoidMain(string[] args)
    {
//Action是.NET Framework内置的泛型委托,要求委托必须无返回值/* Action<参数类型> 委托对象名 = 方法名 */Action[] actions= { Hello, World };
foreach (Actionfuncinactions)
      {
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>funcinfuncArrayC)
      {
FuncAry(func, 114514);
      }
    }
publicstaticvoidFuncAry(FuncDelegrateStringfunc, stringvalue)
    {
Console.WriteLine("");
Console.WriteLine("方法"+GetFunctionName(func) +"返回值是"+func(value));
     }
publicstaticvoidHello()
    {
Console.WriteLine("Hello");
    }
publicstaticvoidWorld()
    {
Console.WriteLine("World");
    }
publicstaticstringHello(stringx)
    {
Console.WriteLine("Hello,"+x);
return"Hello";
    }
publicstaticstringWorld(stringx)
    {
Console.WriteLine(x+"'s World");
returnx;
    }
publicstaticstringWorld(intx)
    {
Console.WriteLine(x+"'s World");
return"World(int x)";
    }
publicstaticintReturnIntValue()
    {
return1;
    }
  }
}
/*输出结果*/HelloWorldHello,114514方法Hello返回值是Hello(intx)
114514's World方法World返回值是World(intx)

四、匿名委托

//这里的Func和delegate都是系统自带不需要声明Func<T>委托对象名=delegate(方法参数){ 
方法体}
namespaceDelegrate{
classProgram  {
staticvoidMain(string[] args)
    {
//匿名方法/* Func<T> 委托对象名 = delegate(方法参数){ 方法体 }; */Func<int, string>AnonymousDelegate=delegate (intx)
      {
return"1";
      };
    }
  }
}

五、委托的多播

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

委托名委托对象A;
委托名委托对象B=new委托名(方法名);
委托名委托对象C=new委托名(方法名);
委托对象A=委托对象B;
委托对象A+=委托对象C;
委托对象A-=委托对象C;
namespaceDelegrate{
classProgram  {
/*声明委托*/publicdelegatevoidFuncDelegrate(); //无参无返回值委托publicdelegatestringFuncDelegrateString(stringx);//有参有返回值委托staticvoidMain(string[] args)
    {
//委托的多播FuncDelegrateStringfds;
FuncDelegrateStringfds1=newFuncDelegrateString(Hello);
FuncDelegrateStringfds2=newFuncDelegrateString(World);
fds=fds1;
fds+=fds2;//表示在委托列表里添加//fds -= fds2;//表示从委托列表里去除fds("Damon");
//第二种写法FuncDelegratefb1=newFuncDelegrate(StaticFeedbackFunc);//这里直接调用的静态方法Programp=newProgram();
FuncDelegratefb2=newFuncDelegrate(p.FeedbackFunc);//非静态方法需要实例化调用FuncDelegratefbChain=null;
fbChain= (FuncDelegrate)Delegate.Combine(fbChain, fb1);//和+=一样fbChain= (FuncDelegrate)Delegate.Combine(fbChain, fb2);
fbChain= (FuncDelegrate)Delegate.Remove(fbChain, newFuncDelegrate(p.FeedbackFunc));//和-=一样    }
publicstaticstringHello(stringx)
    {
Console.WriteLine("Hello,"+x);
return"Hello";
    }
publicstaticstringWorld(stringx)
    {
Console.WriteLine(x+"'s World");
returnx;
    }
publicstaticvoidStaticFeedbackFunc()
   {
Console.WriteLine("StaticFeedbackFunc()");
   }
publicvoidFeedbackFunc()
   {
Console.WriteLine("FeedbackFunc()");
    }
  }
}
/*输出结果*/Hello,DamonDamon's WorldStaticFeedbackFunc()

六、事件

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

publicevent委托类型事件名;
namespaceDelegrate{
/*声明委托*/publicdelegatevoidFuncDelegrate(); //无参无返回值委托classProgram  {
staticvoidMain(string[] args)
    {
//事件/* public event 委托类型 事件名; */DelegrateEventdelegrateEvent=newDelegrateEvent();
delegrateEvent.DelegateEvent+=Hello;//类似delegrateEvent.DelegateEvent+=World;
delegrateEvent.DelegateEvent-=World;
    }
publicstaticvoidHello()
    {
Console.WriteLine("Hello");
    }
publicstaticvoidWorld()
    {
Console.WriteLine("World");
    }
  }
classDelegrateEvent  {
//声明委托,event可以让外部无法直接访问这个委托publiceventFuncDelegrateDelegateEvent=null;
  }
}
目录
相关文章
|
2月前
|
C#
C#一分钟浅谈:委托与事件的实现方式
本文详细介绍了C#编程中委托与事件的基础知识及应用场景。首先解释了委托的概念,包括定义与使用方法;接着介绍了事件这一基于委托的特殊类型,展示了如何在类中定义事件及跨类订阅与处理事件;最后讨论了常见问题如事件未处理异常、重复订阅及内存泄漏等,并提出了相应的解决方案。通过本文,读者将全面掌握委托与事件的使用技巧,提升应用程序的设计与开发水平。
115 7
|
3月前
|
编译器 C#
C#中内置的泛型委托Func与Action
C#中内置的泛型委托Func与Action
64 4
|
3月前
|
C#
C#中的委托(一)
C#中的委托(一)
37 1
|
3月前
|
C# C++
C#语言进阶(一)—委托
C#语言进阶(一)—委托
49 0
|
6月前
|
存储 安全 C#
C# - 委托与事件
这篇文档介绍了C#中的委托和事件。委托是存储方法引用的类型,支持回调、事件处理,具有引用方法、类型安全、多播性等特性,并在异步编程中发挥作用。事件是委托的封装,提供保护和订阅机制,防止外部直接访问。当需要在类内部控制方法调用,防止外部误触发时,可使用事件。
|
5月前
|
C#
C#||委托和事件的实例
C#||委托和事件的实例
|
6月前
|
C#
c#委托详解
c#委托详解
38 0
|
6月前
|
开发框架 安全 .NET
C# .NET面试系列三:集合、异常、泛型、LINQ、委托、EF!
<h2>集合、异常、泛型、LINQ、委托、EF! #### 1. IList 接口与 List 的区别是什么? IList 接口和 List 类是C#中集合的两个相关但不同的概念。下面是它们的主要区别: <b>IList 接口</b> IList 接口是C#中定义的一个泛型接口,位于 System.Collections 命名空间。它派生自 ICollection 接口,定义了一个可以通过索引访问的有序集合。 ```c# IList 接口包含一系列索引化的属性和方法,允许按索引访问、插入、移除元素等。 由于是接口,它只定义了成员的契约,而不提供具体的实现。类似于 IEnumera
347 2
|
6月前
|
Java C# C++
【从Java转C#】第八章:委托、lambda、事件
【从Java转C#】第八章:委托、lambda、事件