C# 委托和事件

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://linsh-tech.blog.csdn.net/article/details/50838089

        听到委托很多人会觉得头疼,因为相较于语言中的其他基本语法,委托的理解成本相对较高一些,但是只要认真去了解其根本原理,你就会发现委托不仅使用简单,而且在我们进行程序开发时还能为我们带来不少便利。

1.什么是委托?

        委托,是寻址的.NET版本,使用委托能够将方法作为参数进行传递。我们也可以把委托当做一种特殊的参数类型,类似于int之类的,用于指定传入参数中的方法的类型。

        所谓方法的类型,实际上就是一个方法的参数结构,例如:a(stringname,intid){}b(stringtitle,intindex){}这两个方法虽然方法名不同,但是他们的参数结构都是(string,int),所以我们可以说他们是属于同一类型的方法。所以,委托就是指定参数结构的方法的集合,也就是一个委托可以代表同种类型参数结构的所有方法。

2.委托的基本案例:

        加入我们需要在不同的情况下根据语音环境来输出一句问候语:"Hello world"、"你好"......为了做分支处理,我们通常的做法是用if...else...或者是用枚举列举所有的情况,然后用switch...case...来处理,这样的方法显然很笨重而且灵活性很差。如下:

int language_type = 0;

static void main(string[] args){

      GreetPeople("Jim",language_type );

      language_type  = 1;

      GreetPeople("半支烟",language_type );

      Console.ReadKey();

}

private voidGreetPeople(string name,inttype){

      if(type == 0){

            PrintChinese(name);

      }else{

            PrintEnglish(name);

      }

}
private void PrintChinese(stringname){
      Console(name+"你好!");
}
private void PrintEnglish(string name){
      Console(name+"Hello!");
}


        我们可以看到假如我们再添加多种类型的语言,那代码就会显得冗余而且缺乏灵活性。其实我们不难发现,虽然PrintChinese和PrintEnglish的方法名不同,但是其参数结构都是(string)这样的结构,所以从委托的角度来看他们属于同一类方法,那当我们引入委托之后,我们的程序会变成什么样子呢?

//定义委托,它定义了可以代表的方法的类型
public delegate void GreetingDelegate(stringname);
static void Main(string[] args) {

      GreetPeople("Jimmy ", PrintChinese);

      GreetPeople("半支烟", PrintEnglish);

      Console.ReadKey();

 }
private void GreetPeople(stringname,GreetingDelegate func){

      func(name);
}
private void PrintChinese(stringname){

      Console(name+"你好!");
}
private void PrintEnglish(stringname){

      Console(name+"Hello!");
}


        在上示的代码中,我们声明了一个委托GreetingDelegate,用它来代表所有参数结构为(string)的方法,当然就包括了PrintChinese和PrintEnglish,然后我们改写了GreetPeople方法的参数,其中func已经不再只是一个简单数据类型的参数,而是一个方法,且其方法类型为GreetingDelegate。这样,我们只需要在调用GreetPeople的时候改表其第二个参数,即所要传入的方法名称,即可实现if...else...所达到的效果,显然简化了代码,而且扩展性很强。

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

3.高级版的委托:

        既然我们说委托是相当于int那样的一种新的类型,那么我们也可以参考int的声明和初始化来使用委托,例如:

static void main(string[] args){

      GreetingDelegate delegate1,delegate2;

      delegate1 = PrintChinese; 

      delegate2 = PrintEnglish;

      GreetPeople("Jimmy ", delegate1);  

      GreetPeople("半支烟", delegate2);

}

        此外,委托不同于string的一个特性:可以将多个方法赋给同一个委托,或者叫将多个方法绑定到同一个委托,当调用这个委托的时候,将依次调用其所绑定的方法。

static void main(string[] args){

      GreetingDelegatedelegate1;

      delegate1 = PrintChinese; 

      delegate1+= PrintEnglish;

      //此时会依次执行PrintChinese和PrintEnglish 

      GreetPeople("Jimmy ", delegate1);

}

        当然,我们也可以直接绕过GreetPeople方法来执行:

static void main(string[] args){

      GreetingDelegatedelegate1;

      //注意这里,第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。

      delegate1 = PrintChinese; 

      delegate1+= PrintEnglish;

      //此时会依次执行PrintChinese和PrintEnglish

      delegate1("Jimmy ");

}

        此外,绑定的操作其实也可以简化,当我们把委托看成一个类时,绑定实际上就是把一些方法绑定到类的一个实例上,例如:

GreetingDelegate delegate1 =newGreetingDelegate(PrintChinese);

delegate1+= PrintEnglish;


        或者:

GreetingDelegate delegate1 =new GreetingDelegate();
delegate1 = PrintChinese;
delegate1+= PrintEnglish;

        既然可以绑定,自然也能解绑,绑定用的是"+=",则解绑就是用"-=",如下:

GreetingDelegate delegate1 =newGreetingDelegate ();
delegate1 = PrintChinese;
delegate1+= PrintEnglish;
delegate1 -= PrintEnglish;

        显然,最后只会执行PrintChinese。

展开阅读全文

没有更多推荐了,返回首页