当前位置:首页 > Windows程序 > 正文

初识C#注册委托

2021-03-25 Windows程序

委托和事件在.NET Framwork中的应用非常广泛。

在初步了解C#的注册委托机制后,认为其作用类似于C++的函数指针。当我们需要在一个函数中将另一个函数作为参数时我们就需要委托机制的帮助。

举例有委托的定义:

public delegate void GreetingDelegate(string name);

编写GreetPeople()方法

public void GreetingPeople(string name,GreetingDelegate MakeGreeting) { MakeGreeting(name); }

实际上,委托在编译的时候确实会编译成类。因为Delegate是一个类,所以在任何可以申明类的地方都可以申明委托。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace 委托_Test { public delegate void GreetingDelegate(string name); class Program { private static void EnglishGreeting(string name) { Console.WriteLine("Morning," + name); } private static void ChineseGreeting(string name) { Console.WriteLine("早上好," + name); } private static void GreetPeople(string name,GreetingDelegate MakeGreeting) { MakeGreeting(name); } static void Main(string[] args) { GreetingDelegate delegate1; delegate1 = ChineseGreeting; //给委托绑定一个方法 delegate1 += EnglishGreeting; //绕过GreetPeople方法 delegate1("李华"); //给委托取消绑定 delegate1 -= EnglishGreeting; GreetPeople("李华", delegate1); string name = "Jimmy"; GreetPeople(name, EnglishGreeting); Console.ReadKey(); } } }


 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,将这种方法动态的赋给参数的做法,可以避免在程序中大量使用if-else(switch)语句,同时使得程序有更好的扩展性。

GreetingDelegate delegate1; delegate1 = ChineseGreeting; delegate1("李华");

我们利用上述代码,我们为委托变量绑定了一个ChineseGreeting方法并绕过了对GreetPeople的调用。

GreetingDelegate delegate1; delegate1 = ChineseGreeting; //给委托绑定一个方法 delegate1 += EnglishGreeting;

上述代码为委托绑定了两个方法。

//给委托取消绑定 delegate1 -= EnglishGreeting;

给委托取消绑定。

string name = "Jimmy"; GreetPeople(name, EnglishGreeting);

最后输出结果为

早上好,李华

Morning,李华

早上好,李华

Morning,Jimmy

在实际应用中通常都是GreetPeople在一个类中,ChineseGreeting和EnglishGreeting在另外的类中。

假设我们将GreetingPeople()放在一个叫做GreetingManager的类中,那么新程序该是这样的的。类GreetingManager

namespace 委托_Test2 { //定义委托,它定义了可以代表的方法的类型 public delegate void GreetingDelegate(string name); class GreetingManager { //注意此方法,它接受一个GreetingDelegate类型的参数,该参数是返回值为空,参数为string类型的方法 public void GreetingPeople(string name,GreetingDelegate MakeGreeting) { MakeGreeting(name); } } }

  Program.cs

namespace 委托_Test2 { class Program { private static void EnglishGreeting(string name) { Console.WriteLine("Morning," + name); } private static void ChineseGreeting(string name) { Console.WriteLine("早上好," + name); } static void Main(string[] args) { //绕过GreetingPeople方法,通过委托来直接调用EnglishGreeting GreetingDelegate delegate1; delegate1 = EnglishGreeting; delegate1("Jimmy"); GreetingManager gm = new GreetingManager(); gm.GreetingPeople("李华", ChineseGreeting); } } }

  面向对象的设计,讲究的是对象的封装,我们可以将委托变量封装到GreetManager类中。可以做如下改写

namespace 委托_Test2 { //定义委托,它定义了可以代表的方法的类型 public delegate void GreetingDelegate(string name); class GreetingManager { public GreetingDelegate delegate2; //注意此方法,它接受一个GreetingDelegate类型的参数,该参数是返回值为空,参数为string类型的方法 public void GreetingPeople(string name,GreetingDelegate MakeGreeting) { MakeGreeting(name); } public void GreetingPeople(string name) { //在GreetingManger类的内部声明delegate2变量 if(delegate2 != null)//如果有方法注册委托变量 { delegate2(name);//通过委托调用方法 } } } }

  我们可以这样使用委托变量:

static void Main(string[] args) { GreetingManager gm = new GreetingManager(); gm.GreetingPeople("李华", ChineseGreeting); gm.delegate2 = ChineseGreeting; gm.delegate2 += EnglishGreeting; gm.GreetingPeople("李华", gm.delegate2); gm.delegate2("李华"); Console.ReadKey(); }

  尽管这样使用可以达到我们的效果,但是还是存在问题。

  在这里,delegate1和我们平时用的string类型的变量没有什么分别,而我们知道,并不是所有的字段都应该声明成public,合适的做法是应该public的时候public,应该private的时候private。

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/67126.html