全球彩票平台_全球彩票注册平台|官网下载地址

热门关键词: 全球彩票平台,全球彩票注册平台,全球彩官网下载地址

【全球彩票注册平台】在派生类中引发基类事件

在派生类中抓住基类事件,派生类引发事件

在基类中宣示能够从派生类引发的事件的规范措施。此形式普遍应用于.Net Framework类库中的Windows窗体类。

小编们来看八个Button类的概念

    public class Button : ButtonBase, IButtonControl
    {
      protected override void OnClick(EventArgs e); //override基类的事件触发程序
    }

作者们透过ButtonBase最终找到基类Control

public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IArrangedElement, IBindableComponent, IComponent, IDisposable
{
    public event EventHandler Click;   //基类中定义事件
    protected virtual void OnClick(EventArgs e);//protected封装事件触发程序,允许继承类调用或重写
}

在满含事件的基类中创设二个受保险的调用方法。通过调用或重写方法,派生类便足以间接调用该事件。

 

大家来看多个例子:

namespace BaseClassEvents
{

    //Special EventArgs class to hold info about Shapes.
    public class ShapeEventArgs:EventArgs
    {
        private double newArea;
        public ShapeEventArgs (double d)
        {
            newArea = d;
        }
        public double NewArea
        {
            get
            {
                return newArea;
            }
        }
    }
    //Declare a delegate
    public delegate void CustomEventHandler(object sender, ShapeEventArgs e);

    //Base class event publisher
    public abstract class Shape
    {
        protected double area;
        public double Area
        {
            get
            {
                return area;
            }
            set
            {
                area = value;
            }
        }
        //raise an event
        public event CustomEventHandler ShapeChanged;

        public abstract void Draw();

        //event-invoking method
        protected virtual void OnShapeChanged(ShapeEventArgs e)
        {
            if(ShapeChanged !=null)
            {
                ShapeChanged(this, e);
            }
        }
    }
    public class Circle:Shape
    {
        private double radius;
        public Circle (double d)
        {
            radius = d;
            area = 3.14 * radius * radius;
        }
        public void Update(double d)
        {
            radius = d;
            area = 3.14 * radius * radius;
            OnShapeChanged(new ShapeEventArgs(area));
        }
        protected override void OnShapeChanged(ShapeEventArgs e)
        {
            base.OnShapeChanged(e);
        }
        public override void Draw()
        {
            Console.WriteLine("Drawing a circle");
        }
    }
    public class Rectangle:Shape
    {
        private double length;
        private double width;
        public Rectangle (double length,double width)
        {
            this.length = length;
            this.width = width;
            area = length * width;
        }
        public void Update(double length,double width)
        {
            this.length = length;
            this.width = width;
            area = length * width;
            OnShapeChanged(new ShapeEventArgs(area));
        }
        protected override void OnShapeChanged(ShapeEventArgs e)
        {
            base.OnShapeChanged(e);
        }
        public override void Draw()
        {
            Console.WriteLine("Drawing a rectangle");
        }
    }

    //Subscriber
    //Represents the surface on which the shapes are drawn
    //Subscibes to shape events so that it knows
    //when to redraw a shape
    public class ShapeContainer
    {
        List<Shape> _list;
        public ShapeContainer ()
        {
            _list = new List<Shape>();
        }
        public void AddShape(Shape s)
        {
            _list.Add(s);
            //Subscribe to the base class event.
            s.ShapeChanged  = HandleShapeChanged;
        }
        private void HandleShapeChanged(object sender,ShapeEventArgs e)
        {
            Shape s = (Shape)sender;
            Console.WriteLine("Received event. Shape area is now {0}", e.NewArea);
            s.Draw();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //Create the event publishers and subscriber
            Circle c1 = new Circle(54);
            Rectangle r1 = new Rectangle(12, 9);
            ShapeContainer sc = new ShapeContainer();

            //Add the shapes to the container
            sc.AddShape(c1);
            sc.AddShape(r1);

            //Cause some events to be raised
            c1.Update(57);
            r1.Update(7, 7);

            Console.ReadKey();
        }
    }
}

 

在基类中扬言能够从派生类引发的风云的正经措施。此情势普遍应用于.Net Framework类库中的Win...

在基类中宣称能够从派生类引发的事件的行业内部方法。此形式广泛应用于.Net Framework类库中的Windows窗体类。

在基类中注脚能够从派生类引发的平地风波的正儿八经方法。此情势广泛应用于.Net Framework类库中的Windows窗体类。

 事件概述                                                           


大家来看多个Button类的定义

我们来看四个Button类的定义

     在产生别的类或对象关切的作业时,类或对象可透过事件通报它们。发送(或吸引)事件的类称为“发行者”,接收(或拍卖)事件的类称为“订户”。

 

    public class Button : ButtonBase, IButtonControl
    {
      protected override void OnClick(EventArgs e); //override基类的事件触发程序
    }
    public class Button : ButtonBase, IButtonControl
    {
      protected override void OnClick(EventArgs e); //override基类的事件触发程序
    }
  • 特点
    • 发行者显明曾几何时引发事件,订户鲜明实行何种操作来响应该事件。
    • 叁个风浪能够有三个订户。叁个订户可管理来自四个发行者的多少个事件。
    • 从不订户的平地风波恒久不会被调用。
    • 事件司空见惯用于通告客商操作
    • 例如二个事变有多少个订户,当引发该事件时,会联手调用多少个事件处理程序,也得以安装异步调用事件。
    • 能够应用事件联合线程。
    • 事件是基于 EventHandler 委托和 伊芙ntArgs 基类的。

事件概述

寄托是一连串型可以被实例化,而事件能够当作将多播委托实行李包裹装的多个目的成员(简化委托调用列表增删方法)但不要新鲜的信托,保养订阅互不影响。

 

大家通过ButtonBase末了找到基类Control

大家通过ButtonBase最终找到基类Control

 事件的订阅和撤除订阅                                       

基本功事件(event)

在.Net中声明事件选择首要词event,使用也极其简单在信托(delegate)后边加上event:

 1     class Program
 2     {
 3         /// <summary>
 4         /// 定义有参无返回值委托
 5         /// </summary>
 6         /// <param name="i"></param>
 7         public delegate void NoReturnWithParameters();
 8         /// <summary>
 9         /// 定义接受NoReturnWithParameters委托类型的事件
10         /// </summary>
11         static event NoReturnWithParameters NoReturnWithParametersEvent;
12         static void Main(string[] args)
13         {
14             //委托方法1
15             {
16                 Action action = new Action(() =>
17                 {
18                     Console.WriteLine("测试委托方法1成功");
19                 });
20                 NoReturnWithParameters noReturnWithParameters = new NoReturnWithParameters(action);
21                 //事件订阅委托
22                 NoReturnWithParametersEvent  = noReturnWithParameters;
23                 //事件取阅委托
24                 NoReturnWithParametersEvent -= noReturnWithParameters;
25             }
26             //委托方法2
27             {
28                 //事件订阅委托
29                 NoReturnWithParametersEvent  = new NoReturnWithParameters(() =>
30                 {
31                     Console.WriteLine("测试委托方法2成功");
32                 });
33             }
34             //委托方法3
35             {
36                 //事件订阅委托
37                 NoReturnWithParametersEvent  = new NoReturnWithParameters(() => Console.WriteLine("测试委托方法3成功"));
38             }
39             //执行事件
40             NoReturnWithParametersEvent();
41             Console.ReadKey();
42         }
43         /*
44          * 作者:Jonins
45          * 出处:http://www.cnblogs.com/jonins/
46          */
47     }

上述代码实践结果:

全球彩票注册平台 1

 

public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IArrangedElement, IBindableComponent, IComponent, IDisposable
{
    public event EventHandler Click;   //基类中定义事件
    protected virtual void OnClick(EventArgs e);//protected封装事件触发程序,允许继承类调用或重写
}
public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IArrangedElement, IBindableComponent, IComponent, IDisposable
{
    public event EventHandler Click;   //基类中定义事件
    protected virtual void OnClick(EventArgs e);//protected封装事件触发程序,允许继承类调用或重写
}

     要是您想编写引发事件时调用的自定义代码,则足以订阅由另外类发布的事件。比如,可以订阅某个按键的“单击”事件,以使应用程序在顾客单击该按键时举办一些实用的操作。

事件揭露&订阅

事件基于委托,为委托提供了一种发表/订阅机制。当使用事件时一般会冒出两种剧中人物:发行者订阅者。

发行者(Publisher)也称为发送者(sender):是带有委托字段的类,它决定何时调用委托广播。

订阅者(Subscriber)也叫做接受者(recevier):是格局指标的收信人,通过在发行者的寄托上调用 =和-=,决定何时最早和竣事监听。三个订阅者不驾驭也不干预别的的订阅者。

来电->开发手机->接电话,那般八个需要,模制订阅发表机制:

 1     /// <summary>
 2     /// 发行者
 3     /// </summary>
 4     public class Publisher
 5     {
 6         /// <summary>
 7         /// 委托
 8         /// </summary>
 9         public delegate void Publication();
10 
11         /// <summary>
12         /// 事件  这里约束委托类型可以为内置委托Action
13         /// </summary>
14         public event Publication AfterPublication;
15         /// <summary>
16         /// 来电事件
17         /// </summary>
18         public void Call()
19         {
20             Console.WriteLine("显示来电");
21             if (AfterPublication != null)//如果调用列表不为空,触发事件
22             {
23                 AfterPublication();
24             }
25         }
26     }
27     /// <summary>
28     /// 订阅者
29     /// </summary>
30     public class Subscriber
31     {
32         /// <summary>
33         /// 订阅者事件处理方法
34         /// </summary>
35         public void Connect()
36         {
37             Console.WriteLine("通话接通");
38         }
39         /// <summary>
40         /// 订阅者事件处理方法
41         /// </summary>
42         public void Unlock()
43         {
44             Console.WriteLine("电话解锁");
45         }
46     }
47     /*
48      * 作者:Jonins
49      * 出处:http://www.cnblogs.com/jonins/
50      */

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             //定义发行者
 6             Publisher publisher = new Publisher();
 7             //定义订阅者
 8             Subscriber subscriber = new Subscriber();
 9             //发行者订阅 当来电需要电话解锁
10             publisher.AfterPublication  = new Publisher.Publication(subscriber.Unlock);
11             //发行者订阅 当来电则接通电话
12             publisher.AfterPublication  = new Publisher.Publication(subscriber.Connect);
13             //来电话了
14             publisher.Call();
15             Console.ReadKey();
16         }
17     }

试行结果:

全球彩票注册平台 2

注意:

1.风波只可以够从申明它们的类中调用, 派生类不恐怕直接调用基类中扬言的事件。

1  publisher.AfterPublication();//这行代码在Publisher类外部调用则编译不通过

2.对那件事件在声明类外界只可以 =,-=不能够直接调用,而委托在外界不只好够应用 =,-=等运算符仍是能够直接调用。

上边调用格局与地点实行结果一律,利用了信托多播的风味。

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Publisher publisher = new Publisher();
 6             Subscriber subscriber = new Subscriber();
 7             //------利用多播委托-------
 8             var publication = new Publisher.Publication(subscriber.Unlock);
 9             publication  = new Publisher.Publication(subscriber.Connect);
10             publisher.AfterPublication  = publication;
11             //---------End-----------
12             publisher.Call();
13             Console.ReadKey();
14         }
15     }

 

在含蓄事件的基类中开创二个受保障的调用方法。通过调用或重写方法,派生类便得以直接调用该事件。

在含蓄事件的基类中开创五个受保证的调用方法。通过调用或重写方法,派生类便得以直接调用该事件。

  • 订阅事件
    • VS IDE 订阅事件
      • 要是“属性”窗口不可知,请在“设计”视图中,右击要开创事件处理程序的窗体或控件,然后选拔“属性”。
      • 在“属性”窗口的顶上部分,单击“事件”Logo。
      • 双击要开创的事件,Visual C# 会创立一个空事件管理程序方法,并将其增多到您的代码中。只怕,您也得以在“代码”视图中手动加多代码。
    • 编制程序格局订阅事件

      • 概念二个事件管理程序方法,其签名与该事件的寄托签字相配。举例,即使事件基于 EventHandler 委托类型,则上边包车型大巴代码表示方法存根

 自定义事件(伊芙ntArgs&EventHandler&事件监听器)

有过Windwos Form开辟经历对上面包车型客车代码会熟知:

1 private void Form1_Load(object sender, EventArgs e)
2 {
3      ...      
4 }

在设计器Form1.Designer.cs中有事件的叠合。这种办法属于Visual Studio IDE事件订阅。

1  this.Load  = new System.EventHandler(this.Form1_Load);

在 .NET Framework 类库中,事件基于 EventHandler 委托和 EventArgs 基类。

基于伊夫ntHandler情势的事件

 1     /// <summary>
 2     /// 事件监听器
 3     /// </summary>
 4     public class Consumer
 5     {
 6         private string _name;
 7 
 8         public Consumer(string name)
 9         {
10             _name = name;
11         }
12         public void Monitor(object sender, CustomEventArgs e)
13         {
14             Console.WriteLine($"Name:{_name}; 信息:{e.Message};到底要不要接呢?");
15         }
16     }
17     /// <summary>
18     /// 定义保存自定义事件信息的对象
19     /// </summary>
20     public class CustomEventArgs : EventArgs//作为事件的参数,必须派生自EventArgs基类
21     {
22         public CustomEventArgs(string message)
23         {
24             this.Message = message;
25         }
26         public string Message { get; set; }
27     }
28     /// <summary>
29     /// 发布者
30     /// </summary>
31     public class Publisher
32     {
33         public event EventHandler<CustomEventArgs> Publication;//定义事件
34         public void Call(string w)
35         {
36             Console.WriteLine("显示来电."   w);
37             OnRaiseCustomEvent(new CustomEventArgs(w));
38         }
39         //在一个受保护的虚拟方法中包装事件调用。
40         //允许派生类覆盖事件调用行为
41         protected virtual void OnRaiseCustomEvent(CustomEventArgs e)
42         {
43             //在空校验之后和事件引发之前。制作临时副本,以避免可能发生的事件。
44             EventHandler<CustomEventArgs> publication = Publication;
45             //如果没有订阅者,事件将是空的。
46             if (publication != null)
47             {
48                 publication(this, e);
49             }
50         }
51     }
52     /// <summary>
53     /// 订阅者
54     /// </summary>
55     public class Subscriber
56     {
57         private string Name;
58         public Subscriber(string name, Publisher pub)
59         {
60             Name = name;
61             //使用c# 2.0语法订阅事件
62             pub.Publication  = UnlockEvent;
63             pub.Publication  = ConnectEvent;
64         }
65         //定义当事件被提起时该采取什么行动。
66         void ConnectEvent(object sender, CustomEventArgs e)
67         {
68             Console.WriteLine("通话接通.{0}.{1}", e.Message, Name);
69         }
70         void UnlockEvent(object sender, CustomEventArgs e)
71         {
72             Console.WriteLine("电话解锁.{0}.{1}", e.Message, Name);
73         }
74     }
75     /*
76      * 作者:Jonins
77      * 出处:http://www.cnblogs.com/jonins/
78      */

调用方式:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Publisher pub = new Publisher();
 6             //加入一个事件监听
 7             Consumer jack = new Consumer("Jack");
 8             pub.Publication  = jack.Monitor;
 9             Subscriber user1 = new Subscriber("中国移动", pub);
10             pub.Call("号码10086");
11             Console.WriteLine("--------------------------------------------------");
12             Publisher pub2 = new Publisher();
13             Subscriber user2 = new Subscriber("中国联通", pub2);
14             pub2.Call("号码10010");
15             Console.ReadKey();
16         }
17     }

结果如下:

全球彩票注册平台 3

1.EventHandler<T>在.NET Framework 2.0中引进,定义了三个管理程序,它回到void,接受七个参数。

1 public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

率先个参数(sender)是多少个对象,蕴含事件的发送者。
其次个参数(e)提供了事件的相干音讯,参数随不相同的风浪类型而改变(承继伊夫ntArgs)。
.NET1.0为持有差异数据类型的平地风波定义了几百个委托,有了泛型委托伊夫ntHandler<T>后,不再要求委托了。

2.EventArgs,标记表示包蕴事件数量的类的基类,并提供用于不带有事件数量的平地风波的值。

1 [System.Runtime.InteropServices.ComVisible(true)]
2 public class EventArgs

3.还要能够依附编制程序格局订阅事件

1     Publisher pub = new Publisher();
2     pub.Publication  = Close;
3     ...
4     //添加一个方法
5     static void Close(object sender, CustomEventArgs a)
6     {
7             // 关闭电话
8     }

4.Consumer类为事件监听器当接触事件时可获得当前宣布者对应自定义新闻目的,能够依靠须求做逻辑编码,再举办事件所订阅的连枪乌贼理。扩大事件订阅/公布机制的健壮性。

5.以线程安全的不二等秘书籍触发事件    

1 EventHandler<CustomEventArgs> publication = Publication;

接触事件是只含有一行代码的次第。那是C#6.0的效用。在头里版本,触发事件此前要做为空剖断。同不经常间在开展null检查测量检验和接触之间,或许另一个线程把事件设置为null。所以需求二个片段变量。在C#6.0中,全部触发都能够运用null传播运算符和贰个代码行代替。

1 Publication?.Invoke(this, e);

只顾:即便定义的类中的事件可依据别的有效委托项目,以致是再次回到值的嘱托,但貌似依然提议使用 EventHandler 使事件基于 .NET Framework 情势。

 

 

 

void HandleCustomEvent(object sender, CustomEventArgs a){  }

线程安全格局触发事件

在地点的例证中,过去科学普及的接触事件有两种方法:

 1             //版本1
 2             if (Publication != null)
 3             {
 4                 Publication();//触发事件
 5             }
 6 
 7             //版本2
 8             var temp = Publication;
 9             if (temp != null)
10             {
11                 temp();//触发事件
12             }
13 
14             //版本3
15             var temp = Volatile.Read(ref Publication);
16             if (temp != null)
17             {
18                 temp();//触发事件
19             }

版本1会发生NullReferenceException异常。

版本2的缓解思路是,将引用赋值到有时变量temp中,前者引用赋值产生时的委托链。所以temp复制后哪怕另多少个线程改动了AfterPublication对象也不曾涉嫌。委托是不行变得,所以理论上有效。不过编写翻译器恐怕通过一丝一毫移除变量temp的章程对上述代码进行优化所以仍或然抛出NullReferenceException.

版本3Volatile.Read()的调用,强迫Publication在这几个调用产生时读取,引用真的必需赋值到temp中,编写翻译器优化代码。然后temp独有再部位null时才被调用。

本子3最全面技术不错,版本2也是足以采用的,因为JIT编写翻译机制上知道不应当优化掉变量temp,所以在局地变量中缓存一个引用,可保险堆应用只被访谈叁次。但他日是不是变动不佳说,所以提议使用版本3。

 

 

咱俩来看一个事例:

大家来看一个例证:

      • 运用加法赋值运算符 ( =) 来为事件附加事件管理程序。在下边包车型地铁身先士卒中,假设名称叫 publisher 的靶子具有叁个名叫 RaiseCustom伊芙nt 的平地风波。请留心,订户类必要援引发行者类才干订阅其事件。

事件揭破

我们再次审视基础事件里的一段代码:

1     public delegate void NoReturnWithParameters();
2     static event NoReturnWithParameters NoReturnWithParametersEvent;

通过反编写翻译大家得以旁观:

全球彩票注册平台 4

编写翻译器也便是做了三次如下封装:

 1 NoReturnWithParameters parameters;
 2 private event NoReturnWithParameters NoReturnWithParametersEvent
 3 {
 4      add {  NoReturnWithParametersEvent =parameters; }
 5      remove {  NoReturnWithParametersEvent-=parameters; }
 6 }
 7 /*
 8  * 作者:Jonins
 9  * 出处:http://www.cnblogs.com/jonins/
10  */

宣示了二个民用的寄托变量,开放八个措施add和remove作为事件访问器用于( =、-=),NoReturnWithParametersEvent被编写翻译为Private从而达成封装外界不恐怕接触事件。

1.委托类型字段是对信托列表尾部的引用,事件发生时会布告这么些列表中的委托。字段开端化为null,表明无侦听者品级对该事件的关切。

2.正是原始代码将事件定义为Public,委托字段也始终是Private.指标是防范外界的代码不科学的操作它。

3.方法add_xxxremove**_xxxC#编写翻译器还自行为艺术生成代码调用(System.Delegate的静态方法CombineRemove**)。

4.图谋删除从未增多过的办法,Delegate的Remove方法内部不做别的交事务经,不会抛出格外或任何警示,事件的主意集体保持不改变。

5.**addremove方法以线程安全**的一种方式更新值(Interlocked Anything情势)。

 

namespace BaseClassEvents
{

    //Special EventArgs class to hold info about Shapes.
    public class ShapeEventArgs:EventArgs
    {
        private double newArea;
        public ShapeEventArgs (double d)
        {
            newArea = d;
        }
        public double NewArea
        {
            get
            {
                return newArea;
            }
        }
    }
    //Declare a delegate
    public delegate void CustomEventHandler(object sender, ShapeEventArgs e);

    //Base class event publisher
    public abstract class Shape
    {
        protected double area;
        public double Area
        {
            get
            {
                return area;
            }
            set
            {
                area = value;
            }
        }
        //raise an event
        public event CustomEventHandler ShapeChanged;

        public abstract void Draw();

        //event-invoking method
        protected virtual void OnShapeChanged(ShapeEventArgs e)
        {
            if(ShapeChanged !=null)
            {
                ShapeChanged(this, e);
            }
        }
    }
    public class Circle:Shape
    {
        private double radius;
        public Circle (double d)
        {
            radius = d;
            area = 3.14 * radius * radius;
        }
        public void Update(double d)
        {
            radius = d;
            area = 3.14 * radius * radius;
            OnShapeChanged(new ShapeEventArgs(area));
        }
        protected override void OnShapeChanged(ShapeEventArgs e)
        {
            base.OnShapeChanged(e);
        }
        public override void Draw()
        {
            Console.WriteLine("Drawing a circle");
        }
    }
    public class Rectangle:Shape
    {
        private double length;
        private double width;
        public Rectangle (double length,double width)
        {
            this.length = length;
            this.width = width;
            area = length * width;
        }
        public void Update(double length,double width)
        {
            this.length = length;
            this.width = width;
            area = length * width;
            OnShapeChanged(new ShapeEventArgs(area));
        }
        protected override void OnShapeChanged(ShapeEventArgs e)
        {
            base.OnShapeChanged(e);
        }
        public override void Draw()
        {
            Console.WriteLine("Drawing a rectangle");
        }
    }

    //Subscriber
    //Represents the surface on which the shapes are drawn
    //Subscibes to shape events so that it knows
    //when to redraw a shape
    public class ShapeContainer
    {
        List<Shape> _list;
        public ShapeContainer ()
        {
            _list = new List<Shape>();
        }
        public void AddShape(Shape s)
        {
            _list.Add(s);
            //Subscribe to the base class event.
            s.ShapeChanged  = HandleShapeChanged;
        }
        private void HandleShapeChanged(object sender,ShapeEventArgs e)
        {
            Shape s = (Shape)sender;
            Console.WriteLine("Received event. Shape area is now {0}", e.NewArea);
            s.Draw();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //Create the event publishers and subscriber
            Circle c1 = new Circle(54);
            Rectangle r1 = new Rectangle(12, 9);
            ShapeContainer sc = new ShapeContainer();

            //Add the shapes to the container
            sc.AddShape(c1);
            sc.AddShape(r1);

            //Cause some events to be raised
            c1.Update(57);
            r1.Update(7, 7);

            Console.ReadKey();
        }
    }
}
namespace BaseClassEvents
{

    //Special EventArgs class to hold info about Shapes.
    public class ShapeEventArgs:EventArgs
    {
        private double newArea;
        public ShapeEventArgs (double d)
        {
            newArea = d;
        }
        public double NewArea
        {
            get
            {
                return newArea;
            }
        }
    }
    //Declare a delegate
    public delegate void CustomEventHandler(object sender, ShapeEventArgs e);

    //Base class event publisher
    public abstract class Shape
    {
        protected double area;
        public double Area
        {
            get
            {
                return area;
            }
            set
            {
                area = value;
            }
        }
        //raise an event
        public event CustomEventHandler ShapeChanged;

        public abstract void Draw();

        //event-invoking method
        protected virtual void OnShapeChanged(ShapeEventArgs e)
        {
            if(ShapeChanged !=null)
            {
                ShapeChanged(this, e);
            }
        }
    }
    public class Circle:Shape
    {
        private double radius;
        public Circle (double d)
        {
            radius = d;
            area = 3.14 * radius * radius;
        }
        public void Update(double d)
        {
            radius = d;
            area = 3.14 * radius * radius;
            OnShapeChanged(new ShapeEventArgs(area));
        }
        protected override void OnShapeChanged(ShapeEventArgs e)
        {
            base.OnShapeChanged(e);
        }
        public override void Draw()
        {
            Console.WriteLine("Drawing a circle");
        }
    }
    public class Rectangle:Shape
    {
        private double length;
        private double width;
        public Rectangle (double length,double width)
        {
            this.length = length;
            this.width = width;
            area = length * width;
        }
        public void Update(double length,double width)
        {
            this.length = length;
            this.width = width;
            area = length * width;
            OnShapeChanged(new ShapeEventArgs(area));
        }
        protected override void OnShapeChanged(ShapeEventArgs e)
        {
            base.OnShapeChanged(e);
        }
        public override void Draw()
        {
            Console.WriteLine("Drawing a rectangle");
        }
    }

    //Subscriber
    //Represents the surface on which the shapes are drawn
    //Subscibes to shape events so that it knows
    //when to redraw a shape
    public class ShapeContainer
    {
        List<Shape> _list;
        public ShapeContainer ()
        {
            _list = new List<Shape>();
        }
        public void AddShape(Shape s)
        {
            _list.Add(s);
            //Subscribe to the base class event.
            s.ShapeChanged  = HandleShapeChanged;
        }
        private void HandleShapeChanged(object sender,ShapeEventArgs e)
        {
            Shape s = (Shape)sender;
            Console.WriteLine("Received event. Shape area is now {0}", e.NewArea);
            s.Draw();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //Create the event publishers and subscriber
            Circle c1 = new Circle(54);
            Rectangle r1 = new Rectangle(12, 9);
            ShapeContainer sc = new ShapeContainer();

            //Add the shapes to the container
            sc.AddShape(c1);
            sc.AddShape(r1);

            //Cause some events to be raised
            c1.Update(57);
            r1.Update(7, 7);

            Console.ReadKey();
        }
    }
}
publisher.RaiseCustomEvent  = HandleCustomEvent;
publisher.RaiseCustomEvent  = new CustomEventHandler(HandleCustomEvent);

结语

类或对象足以由那件事件向其余类或对象布告发出的相干作业。事件选取的是揭露/订阅机制,注解事件的类为发表类,而对那一个事件展开处理的类则为订阅类。而订阅类如何驾驭那些事件产生并管理,那时候要求用到委托。事件的利用离不开委托。可是事件实际不是信托的一种(事件是新鲜的委托的布道并不科学),委托属于类型(type)它指的是汇聚(类,接口,结构,枚举,委托),事件是概念在类里的四个成员。

 

 

 

    • 佚名方式订阅事件
      • 运用加法赋值运算符 ( =) 来为事件附加佚名格局。在底下的亲自去做中,假诺名称为 publisher 的对象具有一个名叫 RaiseCustom伊芙nt 的风云,而且还定义了二个Custom伊芙ntArgs 类以承载某个类其余专用事件新闻。请留神,订户类需求引用publisher 技巧订阅其事件。

参谋文献

 

CLR via C#(第4版) Jeffrey Richter

C#尖端编制程序(第7版) Christian Nagel  (版9、10对事件部分未有多大不相同)

果壳中的C# C#5.0望尘不及指南 Joseph Albahari

...


 

本文由全球彩票平台发布于全球彩票注册平台编程,转载请注明出处:【全球彩票注册平台】在派生类中引发基类事件

TAG标签: 全球彩票平台
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。