• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

C#中事件与委托的区别代码分析

OC/C/C++ 水墨上仙 1573次浏览

很多人说,事件即委托。真的是这样吗?那么微软为何又要定义事件与委托两个概念呢?
其实事件即委托,在我看来,不如这样解释;
委托是委托,事件是封装过的委托。也就是说,事件是面向对象的产物,它只是将委托实例化的产物。
同一个方法,你可以使用委托来调用,你也可以使用事件来调用。那究竟有何不同?
转自:http://blog.csdn.net/chamychen/article/details/8332929

使用委托调用时:

public delegate int Math(int a, int b);  
public class Test  
{  
    public int Add(int a, int b)  
    {  
        return a + b;  
    }  
}  
[TestClass]  
public class UnitTest1  
{  
    [TestMethod]  
    public void TestMethod1()  
    {  
        Math math = new Math(new Test().Add);  
        math(1, 2);  
    }  
}  

使用事件调用时:

public delegate int Math(int a, int b);  
public class Test  
{  
    public event Math MathEvent;  
    public int Add(int a, int b)  
    {  
        return a + b;  
    }  
    public int Operation(int a, int b)  
    {  
        MathEvent = Add;  
        return MathEvent(a, b);  
    }  
}  
[TestClass]  
public class UnitTest1  
{  
    [TestMethod]  
    public void TestMethod1()  
    {  
        Test t = new Test();  
        t.Operation(1, 2);  
    }  
}  

以上示例,也许无法从面向对象的方面给你做到详细的解释。但是我们可以看出,MathEvent事件以符合Math委托签名的方法来实例化,返回的也正是Math委托的实例。这就是我提到过的事件的封装性。同样也是由于事件返回类型为委托,它也支持多播委托,即我另一篇博文《快速理解C#高级概念(一)&nbspDelegate委托》所提到的事件的方法队列。

如果以上你已经看懂,则无须看下面。不过,我还是推荐你看下面的两个示例,更清晰的理解事件和委托的区别。

使用事件时

    public class Heater   
    {  
        private int temperature;  
        public void BoilWater()   
        {  
            for (int i = 1; i <= 100; i++)   
            {  
                temperature = i;  
                if (temperature > 95 && BoilEvent != null)   
                {  
                      
  
  public class Heater   
    {  
        private int temperature;  
        public void BoilWater()   
        {  
            for (int i = 1; i <= 100; i++)   
            {  
                temperature = i;  
                if (temperature > 95 && BoilEvent != null)   
                {  
                    //执行委托,无需知道要执行哪些方法  
                    BoilEvent(temperature);  
                }  
            }  
        }  
        public delegate void BoilHandle(int param);  
        public event BoilHandle BoilEvent;//封装了委托  
    }  
    public class Alarm   
    {  
        public void MakeAlert(int param)   
        {  
            Console.WriteLine("Alarm:水温已经超过{0}度.",param);  
        }  
    }  
    public class Display  
    {  
        public void ShowMsg(int param)  
        {  
            Console.WriteLine("Display:水已烧开,当前温度{0}度.", param);  
        }  
    }  
    [TestClass]  
    public class UnitTest1  
    {  
        [TestMethod]  
        public void TestMethod1()  
        {  
            Heater heater = new Heater();  
            Alarm alarm = new Alarm();  
            //无需实例化委托,直接针对事件添加方法  
            heater.BoilEvent += alarm.MakeAlert;  
            heater.BoilEvent += new Display().ShowMsg;  
            heater.BoilWater();  
        }  
    }  
  
//执行委托,无需知道要执行哪些方法  
                    BoilEvent(temperature);  
                }  
            }  
        }  
        public delegate void BoilHandle(int param);  
        public event BoilHandle BoilEvent;//封装了委托  
    }  
    public class Alarm   
    {  
        public void MakeAlert(int param)   
        {  
            Console.WriteLine("Alarm:水温已经超过{0}度.",param);  
        }  
    }  
    public class Display  
    {  
        public void ShowMsg(int param)  
        {  
            Console.WriteLine("Display:水已烧开,当前温度{0}度.", param);  
        }  
    }  
    [TestClass]  
    public class UnitTest1  
    {  
        [TestMethod]  
        public void TestMethod1()  
        {  
            Heater heater = new Heater();  
            Alarm alarm = new Alarm();  
            //无需实例化委托,直接针对事件添加方法  
            heater.BoilEvent += alarm.MakeAlert;  
            heater.BoilEvent += new Display().ShowMsg;  
            heater.BoilWater();  
        }  
    }  

使用委托时:

public class Heater   
    {  
        private int temperature;  
        public void BoilWater(BoilEvent b)   
        {  
            for (int i = 1; i <= 100; i++)   
            {  
                temperature = i;  
                if (temperature > 95)   
                {  
                    b(temperature);//此处委托无法不实例化,所以只好传递,破坏了封装性。  
                }  
            }  
        }  
        public delegate void BoilEvent(int param);  
    }  
    public class Alarm   
    {  
        public void MakeAlert(int param)   
        {  
            Console.WriteLine("Alarm:水温已经超过{0}度.",param);  
        }  
    }  
    public class Display  
    {  
        public void ShowMsg(int param)  
        {  
            Console.WriteLine("Display:水已烧开,当前温度{0}度.", param);  
        }  
    }  
    [TestClass]  
    public class UnitTest1  
    {  
        [TestMethod]  
        public void TestMethod1()  
        {  
            Heater heater = new Heater();  
            Alarm alarm = new Alarm();  
            Heater.BoilEvent b = new Heater.BoilEvent(alarm.MakeAlert);//委托在此处实例化  
            b += new Display().ShowMsg;  
            heater.BoilWater(b);  
        }  
  
    }  

从以上示例可以总结出:
多播是委托和事件一个很重要的特性,而事件其实是对委托的封装实例化。


喜欢 (0)
加载中……