详细从浅到深讲解委托和事件


 委托和事件在.net中的应用非常广泛,但是很多人都不太了解为什么使用委托?委托的应用有什么优点?接下来就为大家从什么是委托,委托的实现,为什么要使用委托,三个部分进行由浅到深的讲解,存在问题的地方,还请大家指正

 

1.什么是委托?

 从语言的角度来讲,委托就是把事情托付给别人或别的机构办理.

 请看下面一段代码:

public class example:Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        showInfo del = FunShowInfo;//委托和随string等类型一样,可以定义一种参数类型
        Response.Write(del(6).ToString());
    }
    public delegate int showInfo(int i);

    public int FunShowInfo(int info)
    {
        return info;
    }
}

运行结果: 在页面上显示 6


这个例子中,我们把FunShowInfo委托给del,当执行del的时候实现FunShowInfo的运行结果;

说道这里,大家应该对委托有了一定的认识,那么在C#中委托是什么类型呢?

委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递.

委托可以定义在类的内部或外部,因为委托本身就是类,所以类可以定义在哪委托就可以定义在哪。

委托和string等类型一样,可以定义一种参数类型,然后把方法赋值给委托;不同于string的是,他可以接受多个方法的委托,然后调用委托的时候可以调用多个方法;在后面的讲解中会讲道;

 

2.委托的实现

通俗的可以用下面地话描述:

         1.定义一个委托,用关键字delegate ,具有与事件相同的返回值和参数;

         2.声明一个委托,并把事件传给它;

         3.把委托作为参数传递,调用;

 

3.为什么使用委托

看完上面的例子,大家可能会疑问,我直接可以写成下面的代码:

public class example : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
       Response.Write(FunShowInfo(4));
    }
    public int FunShowInfo(int info)
    {
        return info;
    }
}

会实现一样的效果,用委托实现还多写了几行代码;它的意义何在呢?

好,那么请看下面的例子:

public class example : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Hello(langurage.English, "Demi");
        }

        public enum langurage
        {
            Chinese, English
        }

        public void EnglishGreeting(string name)
        {
            Response.Write("Morning" + "\r\n" + name);
        }
        public void ChineseGreeting(string name)
        {
            Response.Write("你好" + "\r\n" + name);
        }
        public void Hello(langurage lan, string name)
        {
            switch (lan)
            {
                case langurage.English:
                    EnglishGreeting(name);
                    break;
                case langurage.Chinese:
                    ChineseGreeting(name);
                    break;
            }
        }
    }

这个代码实现的是.当页面加载的时候,会根据传入的枚举类型和string类型的参数,执行不同的问候方法;但是这个方案的可扩展性很差,如果日后我们需要再添加韩文、日文问候方法,就不得不反复修改枚举和Hello() Case方法,以适应新的需求。

思考:

我们来看Hello这个方法:

Hello(langurage lan, string name)

它接受一个string类型的name参数.然后根据传入的langurage 类型参数lan来switch case判断执行的方法体;试想一下,如果我们传入的参数不通过switch case判断,只是根据参数本身就可以知道执行的方法体,那么岂不是省去了switch case语句,模型如下:

Hello(string name,***LangurageGreeting)

{

LangurageGreeting(name);

}

那怎么实现呢?这里就需要用到委托了----------------请看代码--------------:

 

    public class example : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Hello("Demi", EnglishGreeting);
            Hello("杨幂", ChineseGreeting);
        }

        public delegate void LangurageGreeting(string name);

        private void EnglishGreeting(string name)
        {
            Response.Write("Morning, " + name + "<br/><br/>");
        }

        private void ChineseGreeting(string name)
        {
            Response.Write("早上好, " + name);
        }

        //注意此方法,它接受一个GreetingDelegate类型的方法作为参数
        private static void Hello(string name, LangurageGreeting MakeGreeting)
        {
            MakeGreeting(name);
        }
    }

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

委托是一个引用类型,它具有引用类型所具有的通性.引用类型保存的不是实际值,而是保存对存储在托管堆中的对象的引用.委托保存的是对函数(方法)的引用.

 

在刚开始的时候我们说过,委托和 类型 string 的地位一样,都是定义了一种参数类型,那么,我是不是也可以这么使用委托?

 public class example : Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            LangurageGreeting english = EnglishGreeting;
            LangurageGreeting chinese = ChineseGreeting;

            //这里我们可以给此委托变量再绑定一个方法
            //english += ChineseGreeting;  
            //给此委托变量取消取消一个方法
            //english -= ChineseGreeting; 
            //需要注意一点是,第一次用的“=”,是赋值的语法;第二次,用的是“+=”,是绑定的语法。如果第一次就//使用“+=”,将出现“使用了未赋值的局部变量”的编译错误。
          
            Hello("Demi", english); 
            Hello("杨幂", chinese);
        }

        public delegate void LangurageGreeting(string name);

        private void EnglishGreeting(string name)
        {
            Response.Write("Morning, " + name + "<br/><br/>");
        }
        private void ChineseGreeting(string name)
        {
            Response.Write("早上好, " + name);
        }
        //注意此方法,它接受一个GreetingDelegate类型的方法作为参数
        private static void Hello(string name, LangurageGreeting MakeGreeting)
        { 
            MakeGreeting(name); 
        }
    }


 好了,希望能对你有所帮助.

 

 

 

发布了88 篇原创文章 · 获赞 16 · 访问量 30万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章