您的位置:首页 > 其它

委托入门-事件与委托

2014-09-05 23:40 393 查看

这篇博客是接着上篇博客写得,内容是委托和事件的对比。

还是通过实例来进行说明

普通版

static void Main(string[] args)
        {
            Cat tom = new Cat();
            Mouse sherry = new Mouse("sherry");
            Mouse yara = new Mouse("yara");
          tom.catMove += new Cat.Move(sherry.mouseMove);
            tom.catMove += new Cat.Move(yara.mouseMove);
            tom.CatMove();

        }
    }
    public class Cat {
        public delegate void Move();
        public Move catMove;
        public void CatMove() {
            Console.WriteLine("猫来了");
            catMove();
        }
    }
    public class Mouse
    {
        private string mouse;
        public Mouse(string mouse)
        {
            this.mouse = mouse;
        }
        public void mouseMove()
        {
            Console.WriteLine(mouse + "快跑");
        }


代码分析:

一段非常简单的委托链的代码。实现了一只猫触发了多只老鼠的设定。缺点在于委托变量被公开了。和普通变量不同,委托链中可是存储着大量的方法链条的,如果被不相关类随意改变,其造成的损失可想而知。为了解决安全性的问题,我们通常将变量设置为私有的。但是如果你想这么解决委托的安全问题就会发现失去了delegate的意义。因为无法通过委托给方法指向具体的方法地址了。这个情况下,事件就闪亮登场了。

将上述代码进行修改。

事件版

Mouse tom = new Mouse("TOM");
            Mouse jerry = new Mouse("JERRY");
            Cat harry = new Cat();
            harry.catMove += new Cat.Move(tom.MouseMove);
            harry.catMove += new Cat.Move(jerry.MouseMove);
            harry.CatMove();
            
        }
    }
    
    class Cat {
        public delegate void Move();
        public event Move catMove;
        public void CatMove(){
            Console.WriteLine("猫来了。");
            catMove();
        }
 
    }
    class Mouse {
        private string sa;
        public Mouse(string sa){
            this.sa=sa;
        }
        public void MouseMove(){
           Console.WriteLine(sa+"快跑");
        }


可以发现基本没什么变化,只是多了个event而已。

在event之下,c#究竟为我们做了什么呢。让我们使用reflector来走近它,最终发现代码被编译成下面这个样子

private Move catMove;
public void add_catMove(Move value)
{
    Move move2;
    Move catMove = this.catMove;
    do
    {
        move2 = catMove;
        Move move3 = (Move) Delegate.Combine(move2, value);
        catMove = Interlocked.CompareExchange<Move>(ref this.catMove, move3, move2);
    }
    while (catMove != move2);
}

 

 
  public void add_catMove(Move value)
{
    Move move2;
    Move catMove = this.catMove;
    do
    {
        move2 = catMove;
        Move move3 = (Move) Delegate.Combine(move2, value);
        catMove = Interlocked.CompareExchange<Move>(ref this.catMove, move3, move2);
    }
    while (catMove != move2);
}

 
public void remove_catMove(Move value)
{
    Move move2;
    Move catMove = this.catMove;
    do
    {
        move2 = catMove;
        Move move3 = (Move) Delegate.Remove(move2, value);
        catMove = Interlocked.CompareExchange<Move>(ref this.catMove, move3, move2);
    }
    while (catMove != move2);
}

 

 
  public void remove_catMove(Move value)
{
    Move move2;
    Move catMove = this.catMove;
    do
    {
        move2 = catMove;
        Move move3 = (Move) Delegate.Remove(move2, value);
        catMove = Interlocked.CompareExchange<Move>(ref this.catMove, move3, move2);
    }
    while (catMove != move2);
}


仔细对比我们可以发现在cat类中明明是用public修饰的委托居然变成了私有。不仅仅如此。事件拥有了两个属于自己的公共方法,功能对应于+=和-=。至此我们可以简单地做个总结:委托不仅将委托变成私有的,还自动拥有了add和remove方法,极大地便利了我们的编程。

总结

其实事件也是一种委托。事件是在委托基础上进一步的封装和处理。事件=安全的多播委托
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: