欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

結(jié)合.net框架在C#派生類(lèi)中觸發(fā)基類(lèi)事件及實(shí)現(xiàn)接口事件

 更新時(shí)間:2016年02月01日 14:39:57   投稿:goldensun  
這篇文章主要介紹了結(jié)合.net框架在C#派生類(lèi)中觸發(fā)基類(lèi)事件及實(shí)現(xiàn)接口事件,示例的事件編程中包括接口和類(lèi)的繼承等面向?qū)ο蟮幕A(chǔ)知識(shí),需要的朋友可以參考下

在派生類(lèi)中引發(fā)基類(lèi)事件
以下簡(jiǎn)單示例演示了在基類(lèi)中聲明可從派生類(lèi)引發(fā)的事件的標(biāo)準(zhǔn)方法。此模式廣泛應(yīng)用于 .NET Framework 類(lèi)庫(kù)中的 Windows 窗體類(lèi)。
在創(chuàng)建可用作其他類(lèi)的基類(lèi)的類(lèi)時(shí),應(yīng)考慮如下事實(shí):事件是特殊類(lèi)型的委托,只可以從聲明它們的類(lèi)中調(diào)用。派生類(lèi)無(wú)法直接調(diào)用基類(lèi)中聲明的事件。盡管有時(shí)需要事件僅由基類(lèi)引發(fā),但在大多數(shù)情形下,應(yīng)該允許派生類(lèi)調(diào)用基類(lèi)事件。為此,您可以在包含該事件的基類(lèi)中創(chuàng)建一個(gè)受保護(hù)的調(diào)用方法。通過(guò)調(diào)用或重寫(xiě)此調(diào)用方法,派生類(lèi)便可以間接調(diào)用該事件。
注意:不要在基類(lèi)中聲明虛擬事件,也不要在派生類(lèi)中重寫(xiě)這些事件。C# 編譯器無(wú)法正確處理這些事件,并且無(wú)法預(yù)知的該派生的事件的用戶(hù)是否真正訂閱了基類(lèi)事件。

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


實(shí)現(xiàn)接口事件

接口可聲明事件。下面的示例演示如何在類(lèi)中實(shí)現(xiàn)接口事件。實(shí)現(xiàn)接口事件的規(guī)則與實(shí)現(xiàn)任何接口方法或?qū)傩缘囊?guī)則基本相同。
在類(lèi)中實(shí)現(xiàn)接口事件
在類(lèi)中聲明事件,然后在適當(dāng)?shù)膮^(qū)域調(diào)用該事件。

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);
      }
    }
  }

}

下面的示例演示如何處理以下的不常見(jiàn)情況:您的類(lèi)是從兩個(gè)以上的接口繼承的,每個(gè)接口都含有同名事件)。在這種情況下,您至少要為其中一個(gè)事件提供顯式接口實(shí)現(xiàn)。為事件編寫(xiě)顯式接口實(shí)現(xiàn)時(shí),必須編寫(xiě) add 和 remove 事件訪問(wèn)器。這兩個(gè)事件訪問(wèn)器通常由編譯器提供,但在這種情況下編譯器不能提供。
您可以提供自己的訪問(wèn)器,以便指定這兩個(gè)事件是由您的類(lèi)中的同一事件表示,還是由不同事件表示。例如,根據(jù)接口規(guī)范,如果事件應(yīng)在不同時(shí)間引發(fā),則可以將每個(gè)事件與類(lèi)中的一個(gè)單獨(dú)實(shí)現(xiàn)關(guān)聯(lián)。在下面的示例中,訂戶(hù)將形狀引用強(qiáng)制轉(zhuǎn)換為 IShape 或 IDrawingObject,從而確定自己將會(huì)接收哪個(gè) 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.

相關(guān)文章

  • 輕松學(xué)習(xí)C#的foreach迭代語(yǔ)句

    輕松學(xué)習(xí)C#的foreach迭代語(yǔ)句

    輕松學(xué)習(xí)C#的foreach迭代語(yǔ)句,  C#語(yǔ)言提供了一個(gè)for語(yǔ)句循環(huán)的捷徑,而且還促進(jìn)了集合類(lèi)的更為一致,就是本文提到的foreach語(yǔ)句,感興趣的小伙伴們可以參考一下
    2015-11-11
  • c#隱藏基類(lèi)方法的作用

    c#隱藏基類(lèi)方法的作用

    這篇文章主要介紹了c#隱藏基類(lèi)方法的作用,大家可以參考使用
    2013-12-12
  • unity3D實(shí)現(xiàn)攝像機(jī)抖動(dòng)特效

    unity3D實(shí)現(xiàn)攝像機(jī)抖動(dòng)特效

    這篇文章主要為大家詳細(xì)介紹了unity3D實(shí)現(xiàn)攝像機(jī)抖動(dòng)特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-01-01
  • C#環(huán)形緩沖區(qū)(隊(duì)列)完全實(shí)現(xiàn)

    C#環(huán)形緩沖區(qū)(隊(duì)列)完全實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了C#環(huán)形緩沖區(qū)(隊(duì)列)完全實(shí)現(xiàn)代碼,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 深入理解.NET中的異步

    深入理解.NET中的異步

    異步編程是程序設(shè)計(jì)的重點(diǎn),在實(shí)際的項(xiàng)目,在大量的數(shù)據(jù)入庫(kù)以及查詢(xún)數(shù)據(jù)并進(jìn)行計(jì)算的時(shí)候,程序的UI界面往往卡死在那里,這時(shí)候就需要對(duì)計(jì)算時(shí)間限制的過(guò)程進(jìn)行異步處理,同時(shí)正確的使用異步編程去處理計(jì)算限制的操作和耗時(shí)IO操作還能提升的應(yīng)用程序的吞吐量及性能
    2021-06-06
  • C#生成帶logo的二維碼

    C#生成帶logo的二維碼

    帶logo的二維碼生成分為兩步驟:首先根據(jù)輸入的內(nèi)容生成二維碼圖片,然后讀取本地的logo圖片,通過(guò)圖片處理生成帶logo的二維碼。本文對(duì)此進(jìn)行介紹,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • C#實(shí)現(xiàn)大數(shù)字運(yùn)算的實(shí)例代碼

    C#實(shí)現(xiàn)大數(shù)字運(yùn)算的實(shí)例代碼

    這篇文章介紹了C#實(shí)現(xiàn)大數(shù)字運(yùn)算的實(shí)例代碼,有需要的朋友可以參考一下
    2013-10-10
  • C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典

    C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典

    這篇文章主要介紹了C# 如何實(shí)現(xiàn)一個(gè)基于值相等性比較的字典,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2021-02-02
  • C#實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換

    C#實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換

    這篇文章介紹了C#實(shí)現(xiàn)進(jìn)制轉(zhuǎn)換的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C#單線(xiàn)程和多線(xiàn)程端口掃描器詳解

    C#單線(xiàn)程和多線(xiàn)程端口掃描器詳解

    這篇文章主要為大家詳細(xì)介紹了C#單線(xiàn)程和多線(xiàn)程端口掃描器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07

最新評(píng)論