文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>【More Effective C#】仅声明非虚的事件

【More Effective C#】仅声明非虚的事件

时间:2010-10-13  来源:空逸云

C#除了可以声明虚方法,属性外,也可以声明虚事件.但是并不建议使用虚事件.因为这常会带来不可预测的Bug.我们定义了一个WorkerEngine类.它有一个虚事件.

 


public abstract class WorkerEngineBase
    {
        public virtual event EventHandler<WorkerEventArgs> OnProgress;
        public void DoLotsOfStuff()
        {
            OnProgress+=new EventHandler<WorkerEventArgs>(WorkerEngineBase_OnProgress);
            WorkerEventArgs args = new WorkerEventArgs();
            args.Percent = 2;
            EventHandler<WorkerEventArgs> progHandler = OnProgress;
            if (progHandler != null)
            {
                progHandler(this, args);
            }
            if (args.Cancel)
                return;
        }
        void WorkerEngineBase_OnProgress(object sender, WorkerEventArgs e)
        {
            Console.WriteLine("WorkerEngineBase class event.");
        }
        protected abstract void SomeWork();
    }

    public class WorkerEventArgs : EventArgs
    {
        public int Percent { get; set; }
        public bool Cancel { get; set; }
    }

 

 C#3.0中.编译器将会自动创建私有字段,以及公共add和remove方法.

 


    Private EventHandler<WorkerEventArgs>progressEvent;
    Public virtual event EventHandler<WorkerEventArgs>OnOrigress
    {
    Add
    {
    progressEvent+=value;
    }
    Remove
    {
    progressEvent-=value;
    }
    }

 

  由于该私有字段是编译器生成的.所以你无法通过代码访问.而且,派生事件将隐藏基类中的事件,派生类所作的工作与原始版本完全一致.即基类有一个自己的私有委托字段,派生类自己也有一个.两个互不相干.

 


public class WorkerEngineDerived : WorkerEngineBase
    {
        protected override void SomeWork()
        {
            //...do some thing;
        }

        public override event EventHandler<WorkerEventArgs> OnProgress;
    }
    
    //调用
WorkerEngineDerived worker = new WorkerEngineDerived();
worker.DoLotsOfStuff();

 

 结果并不与我们所想象的一致.

 

这里如前面所说.派生类访问的事件是派生类自己的事件.而非基类的事件..如果对派生类事件赋值.那么基类中的隐藏私有字段将不会得到赋值.其他类型订阅到的是派生类中的事件.解决的方案是基类使用类似字段方式声明的事件.

 


public class WorkerEngineDerived : WorkerEngineBase
    {
        protected override void SomeWork()
        {
            //...do some thing;
        }

        public override event EventHandler<WorkerEventArgs> OnProgress
        {
            add
            {
                base.OnProgress += value;
            }
            remove { base.OnProgress -= value; }
        }
    }

 

 子类以属性的方式重写.那么结果很显然便是我们所期望的

 

在创建虚事件时,不要使用字段方式的语法,而应该采用属性式的语法.

我们也可以创建一个虚方法,在定义虚事件后调用该方法触发,所有的派生类必须重写触发事件的方法以及虚事件.

 


public abstract class WorkerEngineBase
    {
        public virtual event EventHandler<WorkerEventArgs> OnProgress;

        protected virtual WorkerEventArgs RaiseEvent(WorkerEventArgs args)
        {
            EventHandler<WorkerEventArgs> progHandler = OnProgress;
            if (progHandler != null)
                progHandler(this, args);
            return args;
        }

        public void DoLotsOfStuff()
        {
            OnProgress += new EventHandler<WorkerEventArgs>(WorkerEngineBase_OnProgress);
            WorkerEventArgs args = new WorkerEventArgs();
            args.Percent = 2;
            RaiseEvent(args);
            if (args.Cancel)
                return;
        }

        void WorkerEngineBase_OnProgress(object sender, WorkerEventArgs e)
        {
            Console.WriteLine("WorkerEngineBase class event.");
        }

        protected abstract void SomeWork();
    }
    
 public class WorkerEngineDerived : WorkerEngineBase
    {
        protected override void SomeWork()
        {
            //...do some thing;
        }

        public override event EventHandler<WorkerEventArgs> OnProgress;

        protected override WorkerEventArgs RaiseEvent(WorkerEventArgs args)
        {
            EventHandler<WorkerEventArgs> proghandler = OnProgress;
            if (proghandler != null)
                proghandler(this, args);
            return args;
        }
    }

 

相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载