国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

結合.net框架在C#派生類中觸發基類事件及實現接口事件

2020-01-24 01:17:35
字體:
來源:轉載
供稿:網友

在派生類中引發基類事件
以下簡單示例演示了在基類中聲明可從派生類引發的事件的標準方法。此模式廣泛應用于 .NET Framework 類庫中的 Windows 窗體類。
在創建可用作其他類的基類的類時,應考慮如下事實:事件是特殊類型的委托,只可以從聲明它們的類中調用。派生類無法直接調用基類中聲明的事件。盡管有時需要事件僅由基類引發,但在大多數情形下,應該允許派生類調用基類事件。為此,您可以在包含該事件的基類中創建一個受保護的調用方法。通過調用或重寫此調用方法,派生類便可以間接調用該事件。
注意:不要在基類中聲明虛擬事件,也不要在派生類中重寫這些事件。C# 編譯器無法正確處理這些事件,并且無法預知的該派生的事件的用戶是否真正訂閱了基類事件。

namespace BaseClassEvents{  using System;  using System.Collections.Generic;  // 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; }    }  }  // Base class event publisher  public abstract class Shape  {    protected double area;    public double Area    {      get { return area; }      set { area = value; }    }    // The event. Note that by using the generic EventHandler<T> event type    // we do not need to declare a separate delegate type.    public event EventHandler<ShapeEventArgs> ShapeChanged;    public abstract void Draw();    //The event-invoking method that derived classes can override.    protected virtual void OnShapeChanged(ShapeEventArgs e)    {      // Make a temporary copy of the event to avoid possibility of      // a race condition if the last subscriber unsubscribes      // immediately after the null check and before the event is raised.      EventHandler<ShapeEventArgs> handler = ShapeChanged;      if (handler != null)      {        handler(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)    {      // Do any circle-specific processing here.      // Call the base class event invocation method.      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)    {      // Do any rectangle-specific processing here.      // Call the base class event invocation method.      base.OnShapeChanged(e);    }    public override void Draw()    {      Console.WriteLine("Drawing a rectangle");    }  }  // Represents the surface on which the shapes are drawn  // Subscribes 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;    }    // ...Other methods to draw, resize, etc.    private void HandleShapeChanged(object sender, ShapeEventArgs e)    {      Shape s = (Shape)sender;      // Diagnostic message for demonstration purposes.      Console.WriteLine("Received event. Shape area is now {0}", e.NewArea);      // Redraw the shape here.      s.Draw();    }  }  class Test  {    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);      // Keep the console window open in debug mode.      System.Console.WriteLine("Press any key to exit.");      System.Console.ReadKey();    }  }}

輸出:

    Received event. Shape area is now 10201.86    Drawing a circle    Received event. Shape area is now 49    Drawing a rectangle


實現接口事件

接口可聲明事件。下面的示例演示如何在類中實現接口事件。實現接口事件的規則與實現任何接口方法或屬性的規則基本相同。
在類中實現接口事件
在類中聲明事件,然后在適當的區域調用該事件。

namespace ImplementInterfaceEvents{  public interface IDrawingObject  {    event EventHandler ShapeChanged;  }  public class MyEventArgs : EventArgs   {    // class members  }  public class Shape : IDrawingObject  {    public event EventHandler ShapeChanged;    void ChangeShape()    {      // Do something here before the event…      OnShapeChanged(new MyEventArgs(/*arguments*/));      // or do something here after the event.     }    protected virtual void OnShapeChanged(MyEventArgs e)    {      if(ShapeChanged != null)      {        ShapeChanged(this, e);      }    }  }}

下面的示例演示如何處理以下的不常見情況:您的類是從兩個以上的接口繼承的,每個接口都含有同名事件)。在這種情況下,您至少要為其中一個事件提供顯式接口實現。為事件編寫顯式接口實現時,必須編寫 add 和 remove 事件訪問器。這兩個事件訪問器通常由編譯器提供,但在這種情況下編譯器不能提供。
您可以提供自己的訪問器,以便指定這兩個事件是由您的類中的同一事件表示,還是由不同事件表示。例如,根據接口規范,如果事件應在不同時間引發,則可以將每個事件與類中的一個單獨實現關聯。在下面的示例中,訂戶將形狀引用強制轉換為 IShape 或 IDrawingObject,從而確定自己將會接收哪個 OnDraw 事件。

namespace WrapTwoInterfaceEvents{  using System;  public interface IDrawingObject  {    // Raise this event before drawing    // the object.    event EventHandler OnDraw;  }  public interface IShape  {    // Raise this event after drawing    // the shape.    event EventHandler OnDraw;  }  // Base class event publisher inherits two  // interfaces, each with an OnDraw event  public class Shape : IDrawingObject, IShape  {    // Create an event for each interface event    event EventHandler PreDrawEvent;    event EventHandler PostDrawEvent;    object objectLock = new Object();    // Explicit interface implementation required.    // Associate IDrawingObject's event with    // PreDrawEvent    event EventHandler IDrawingObject.OnDraw    {      add      {        lock (objectLock)        {          PreDrawEvent += value;        }      }      remove      {        lock (objectLock)        {          PreDrawEvent -= value;        }      }    }    // Explicit interface implementation required.    // Associate IShape's event with    // PostDrawEvent    event EventHandler IShape.OnDraw    {      add      {        lock (objectLock)        {          PostDrawEvent += value;        }      }      remove      {        lock (objectLock)        {          PostDrawEvent -= value;        }      }    }    // For the sake of simplicity this one method    // implements both interfaces.     public void Draw()    {      // Raise IDrawingObject's event before the object is drawn.      EventHandler handler = PreDrawEvent;      if (handler != null)      {        handler(this, new EventArgs());      }      Console.WriteLine("Drawing a shape.");      // RaiseIShape's event after the object is drawn.      handler = PostDrawEvent;      if (handler != null)      {        handler(this, new EventArgs());      }    }  }  public class Subscriber1  {    // References the shape object as an IDrawingObject    public Subscriber1(Shape shape)    {      IDrawingObject d = (IDrawingObject)shape;      d.OnDraw += new EventHandler(d_OnDraw);    }    void d_OnDraw(object sender, EventArgs e)    {      Console.WriteLine("Sub1 receives the IDrawingObject event.");    }  }  // References the shape object as an IShape  public class Subscriber2  {    public Subscriber2(Shape shape)    {      IShape d = (IShape)shape;      d.OnDraw += new EventHandler(d_OnDraw);    }    void d_OnDraw(object sender, EventArgs e)    {      Console.WriteLine("Sub2 receives the IShape event.");    }  }  public class Program  {    static void Main(string[] args)    {      Shape shape = new Shape();      Subscriber1 sub = new Subscriber1(shape);      Subscriber2 sub2 = new Subscriber2(shape);      shape.Draw();      // Keep the console window open in debug mode.      System.Console.WriteLine("Press any key to exit.");      System.Console.ReadKey();    }  }}

輸出:

  Sub1 receives the IDrawingObject event.  Drawing a shape.  Sub2 receives the IShape event.

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 耿马| 南川市| 沅陵县| 银川市| 滁州市| 郧西县| 邹城市| 永仁县| 宁陵县| 宜黄县| 收藏| 惠安县| 城市| 西乌珠穆沁旗| 襄樊市| 丹棱县| 吴忠市| 油尖旺区| 乌拉特前旗| 威宁| 南开区| 大理市| 犍为县| 修水县| 石泉县| 荣昌县| 大洼县| 永寿县| 龙岩市| 包头市| 新沂市| 顺昌县| 綦江县| 北川| 郯城县| 开鲁县| 舒城县| 老河口市| 武川县| 温泉县| 四会市|