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

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

深入解析C#編程中的事件

2019-11-18 19:42:18
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  一個(gè)事件是一個(gè)使對(duì)象或類可以提供公告的成員。用戶可以通過(guò)提供事件句柄來(lái)為事件添加可執(zhí)行代碼。事件使用事件聲明來(lái)聲明:

  一個(gè)事件聲明既可以是一個(gè)事件域聲明也可以是事件屬性聲明。在每種情況中,聲明都可以由屬性集合, new 修飾符, 四個(gè)訪問(wèn)修飾符的有效組合 和一個(gè)靜態(tài)修飾符組成。

  一個(gè)事件聲明的類型必須是一個(gè)代表類型, 而那個(gè)代表類型必須至少同事件本身一樣可訪問(wèn)。

  一個(gè)事件域聲明與一個(gè)聲明了一個(gè)或多個(gè)代表類型域的域聲明相應(yīng)。在一個(gè)事件域聲明中不允許有readonly 修飾符。

  一個(gè)事件屬性聲明與聲明了一個(gè)代表類型屬性的屬性聲明相應(yīng)。除了同時(shí)包含get訪問(wèn)符和set訪問(wèn)符的事件屬性聲明,成員名稱和訪問(wèn)符聲明對(duì)于那些屬性聲明來(lái)說(shuō)都是相同的,并且不允許包含virtual、 override和abstract 修飾符。

  在包含一個(gè)事件成員聲明的類或結(jié)構(gòu)的程序文字中,事件成員與代表類型的私有域或?qū)傩韵嚓P(guān),而這個(gè)成員可以用于任何允許使用域或?qū)傩缘纳舷挛闹小?/P>

  如果一個(gè)類或結(jié)構(gòu)的程序文字外面包含一個(gè)事件成員聲明,這個(gè)事件成員就只能被作為+= 和 -= 操作符 (§的右手操作數(shù)使用。這些操作符被用來(lái)為事件成員附加或去掉事件句柄,而這個(gè)事件成員的訪問(wèn)操作符控制操作在其中被執(zhí)行的上下文。

  由于+= 和 -= 是唯一可以在聲明了事件成員的類型外的事件上使用的操作,外部代碼可以為一個(gè)事件添加或去掉句柄,但是不能通過(guò)任何其他途徑獲得或修改基本事件域或事件屬性的數(shù)值。

  在例子中

public delegate void EventHandler(object sender, Event e);
public class Button: Control
{
 public event EventHandler Click;
 PRotected void OnClick(Event e) {
  if (Click != null) Click(this, e);
 }
 public void Reset() {
  Click = null;
 }
}

  對(duì)使用Button類中的Click事件域沒有限制。作為演示的例子,這個(gè)域可以在代表調(diào)用表達(dá)式中被檢驗(yàn)、修改和使用。類Button中的OnClick方法"引起"Click事件。引起一個(gè)事件的概念與調(diào)用由事件成員表示的代表正好相同-因此,對(duì)于引起事件沒有特殊的語(yǔ)言構(gòu)造。注意代表的調(diào)用是通過(guò)檢查保證代表是非空后才進(jìn)行的。

  在類Button的聲明外面,成員Click只能被用在+= 和 -= 操作符右手邊,如下

b.Click += new EventHandler(...);

  它把一個(gè)代表附加到事件Click的調(diào)用列表中,并且

b.Click -= new EventHandler(...);

  它把一個(gè)代表從Click事件的調(diào)用列表中刪除。

  在一個(gè)形式為x += y 或 x -= y的操作中,當(dāng)x是一個(gè)事件成員而引用在包含x的聲明的類型外面發(fā)生時(shí),操作的結(jié)果就是void(在賦值后與x的數(shù)值相反)。這個(gè)規(guī)則禁止外部代碼直接檢查事件成員的基本代表。
下面的例子介紹了事件句柄如何附加到上面的類Button的實(shí)例中:

public class LoginDialog: Form
{
 Button OkButton;
 Button CancelButton;
 public LoginDialog() {
  OkButton = new Button(...);
  OkButton.Click += new EventHandler(OkButtonClick);
  CancelButton = new Button(...);
  CancelButton.Click += new EventHandler(CancelButtonClick);
 }
 void OkButtonClick(object sender, Event e) {
  // Handle OkButton.Click event
 }
 void CancelButtonClick(object sender, Event e) {
  // Handle CancelButton.Click event
 }
}

  這里,構(gòu)造函數(shù)LoginDialog創(chuàng)建了兩個(gè)Button實(shí)例,并且把事件句柄附加到事件Click中。

  事件成員是典型域,就像上面的Button例子中所示。在每個(gè)事件消耗一個(gè)域存儲(chǔ)的情況是不可接受的,一個(gè)類可以聲明事件屬性來(lái)替代事件域,并且使用私有機(jī)制來(lái)存儲(chǔ)基本的代表。(設(shè)想在某種情況下,大多數(shù)事件都是未處理的,每個(gè)事件使用一個(gè)域就不能被接受。使用屬性而不是域的能力允許開發(fā)人員在空間和時(shí)間上面取得一個(gè)折中方案。)

  在例子中

class Control: Component
{
 // Unique keys for events
 static readonly object mouseDownEventKey = new object();
 static readonly object mouseUpEventKey = new object();
 // Return event handler associated with key
 protected Delegate GetEventHandler(object key) {...}
 // Set event handler associated with key
 protected void SetEventHandler(object key, Delegate handler) {...}
 // MouseDown event property
 public event MouseEventHandler MouseDown {
  get {
   return (MouseEventHandler)GetEventHandler(mouseDownEventKey);
  }
  set {
   SetEventHandler(mouseDownEventKey, value);
  }
 }
 // MouseUp event property
 public event MouseEventHandler MouseUp {
  get {
   return (MouseEventHandler)GetEventHandler(mouseUpEventKey);
  }
  set {
   SetEventHandler(mouseUpEventKey, value);
  }
}
}

  類Control為事件提供了一種內(nèi)部存儲(chǔ)機(jī)制。方法SetEventHandler用一個(gè)key來(lái)與代表數(shù)值相關(guān),而方法GetEventHandler返回與key相關(guān)的當(dāng)前代表。大概基本的存儲(chǔ)機(jī)制是按照把空代表類型與key相關(guān)不會(huì)有消耗而設(shè)計(jì)的,因此無(wú)句柄的事件不占用存儲(chǔ)空間。
  實(shí)例變量初始化函數(shù)

  當(dāng)一個(gè)構(gòu)造函數(shù)沒有構(gòu)造初始化函數(shù)或一個(gè)形式為base(...)的構(gòu)造函數(shù)初始化函數(shù),構(gòu)造函數(shù)就就隱含的執(zhí)行被類中聲明的實(shí)例域的變量初始化函數(shù)指定的初始化。這與賦值序列相關(guān),這些賦值在直接基類構(gòu)造函數(shù)的隱式調(diào)用前,在構(gòu)造函數(shù)的入口被直接執(zhí)行。變量初始化函數(shù)按照它們?cè)陬惵暶髦谐霈F(xiàn)的文字順序執(zhí)行。

  構(gòu)造函數(shù)執(zhí)行

  可以把一個(gè)實(shí)例變量初始化函數(shù)和一個(gè)構(gòu)造函數(shù)初始化函數(shù),看作是自動(dòng)插在構(gòu)造函數(shù)主體中的第一條語(yǔ)句前。例子

using System.Collections;
class A
{
 int x = 1, y = -1, count;
 public A() {
  count = 0;
 }
 public A(int n) {
  count = n;
 }
}
class B: A
{
 double sqrt2 = Math.Sqrt(2.0);
 ArrayList items = new ArrayList(100);
 int max;
 public B(): this(100) {
  items.Add("default");
 }
 public B(int n): base(n - 1) {
  max = n;
 }
}

  包含了許多變量初始化函數(shù),并且也包含了每個(gè)形式(base和this)的構(gòu)造函數(shù)初始化函數(shù)。這個(gè)例子與下面介紹的例子相關(guān),在那里,每條注釋指明了一個(gè)自動(dòng)插入的語(yǔ)句(自動(dòng)插入構(gòu)造函數(shù)調(diào)用所使用的語(yǔ)法不是有效的,至少用來(lái)演示這個(gè)機(jī)制)。

using System.Collections;
class A
{
 int x, y, count;
 public A() {
  x = 1; // Variable initializer
  y = -1; // Variable initializer
  object(); // Invoke object() constructor
  count = 0;
 }
 public A(int n) {
  x = 1; // Variable initializer
  y = -1; // Variable initializer
  object(); // Invoke object() constructor
  count = n;
 }
}
class B: A
{
 double sqrt2;
 ArrayList items;
 int max;
 public B(): this(100) {
  B(100); // Invoke B(int) constructor
  items.Add("default");
 }
 public B(int n): base(n - 1) {
  sqrt2 = Math.Sqrt(2.0); // Variable initializer
  items = new ArrayList(100); // Variable initializer
  A(n - 1); // Invoke A(int) constructor
  max = n;
 }
}
 

  注意變量初始化函數(shù)被轉(zhuǎn)換為賦值語(yǔ)句,并且那個(gè)賦值語(yǔ)句在對(duì)基類構(gòu)造函數(shù)調(diào)用前執(zhí)行。這個(gè)順序確保了所有實(shí)例域在任何訪問(wèn)實(shí)例的語(yǔ)句執(zhí)行前,被它們的變量初始化函數(shù)初始化。例如:

class A
{
 public A() {
  PrintFields();
 }
 public virtual void PrintFields() {}
}
class B: A
{
 int x = 1;
 int y;
 public B() {
  y = -1;
 }
 public override void PrintFields() {
  Console.WriteLine("x = {0}, y = {1}", x, y);
 }
}
 

  當(dāng)new B() 被用來(lái)創(chuàng)建B的實(shí)例時(shí),產(chǎn)生下面的輸出:

x = 1, y = 0

  因?yàn)樽兞砍跏蓟瘮?shù)在基類構(gòu)造函數(shù)被調(diào)用前執(zhí)行,所以x的數(shù)值是1。可是,y的數(shù)值是0(int的默認(rèn)數(shù)值),這是因?yàn)閷?duì)y的賦值直到基類構(gòu)造函數(shù)返回才被執(zhí)行。

  默認(rèn)構(gòu)造函數(shù)

  如果一個(gè)類不包含任何構(gòu)造函數(shù)聲明,就會(huì)自動(dòng)提供一個(gè)默認(rèn)的構(gòu)造函數(shù)。默認(rèn)的構(gòu)造函數(shù)通常是下面的形式

public C(): base() {}

  這里C是類的名稱。默認(rèn)構(gòu)造函數(shù)完全調(diào)用直接基類的無(wú)參數(shù)構(gòu)造函數(shù)。如果直接基類中沒有可訪問(wèn)的無(wú)參數(shù)構(gòu)造函數(shù),就會(huì)發(fā)生錯(cuò)誤。在例子中

class Message
{
 object sender;
 string text;
}

  因?yàn)轭惒话瑯?gòu)造函數(shù)聲明,所以提供了一個(gè)默認(rèn)構(gòu)造函數(shù)。因此,這個(gè)例子正好等同于

class Message
{
 object sender;
 string text;
 public Message(): base() {}
}
  私有構(gòu)造函數(shù)

  當(dāng)一個(gè)類只聲明了私有的構(gòu)造函數(shù)時(shí),其他類就不能從這個(gè)類派生或創(chuàng)建類的實(shí)例。私有構(gòu)造函數(shù)通常用在只包含靜態(tài)成員的類中。例如:

public class Trig
{
private Trig() {} // Prevent instantiation
public const double PI = 3.14159265358979323846;
public static double Sin(double x) {...}
public static double Cos(double x) {...}
public static double Tan(double x) {...}
}

  Trig 類提供了一組相關(guān)的方法和常數(shù),但沒有被例示。因此,它聲明了一個(gè)單獨(dú)的私有構(gòu)造函數(shù)。注意至少要必須聲明一個(gè)私有構(gòu)造函數(shù)來(lái)避免自動(dòng)生成默認(rèn)的構(gòu)造函數(shù)(它通常有公共的訪問(wèn)性)。

  可選的構(gòu)造函數(shù)參數(shù)

  構(gòu)造函數(shù)的this(...) 形式通常用于與實(shí)現(xiàn)可選的構(gòu)造函數(shù)參數(shù)的關(guān)聯(lián)上。在這個(gè)例子中

class Text
{
 public Text(): this(0, 0, null) {}
 public Text(int x, int y): this(x, y, null) {}
 public Text(int x, int y, string s) {
  // Actual constructor implementation
 }
}

  前兩個(gè)構(gòu)造函數(shù)只是為丟失的參數(shù)提供了默認(rèn)的數(shù)值。兩個(gè)都使用了一個(gè)this(...)構(gòu)造函數(shù)的初始化函數(shù)來(lái)調(diào)用第三個(gè)構(gòu)造函數(shù),它實(shí)際上做了對(duì)新實(shí)例進(jìn)行初始化的工作。效果是那些可選的構(gòu)造函數(shù)參數(shù):

Text t1 = new Text(); // Same as Text(0, 0, null)
Text t2 = new Text(5, 10); // Same as Text(5, 10, null)
Text t3 = new Text(5, 20, "Hello");

  析構(gòu)函數(shù)

  析構(gòu)函數(shù)是一個(gè)實(shí)現(xiàn)破壞一個(gè)類的實(shí)例的行為的成員。析構(gòu)函數(shù)使用析構(gòu)函數(shù)聲明來(lái)聲明:

  一個(gè)析構(gòu)函數(shù)聲明的標(biāo)識(shí)符必須為聲明析構(gòu)函數(shù)的類命名,如果指定了任何其他名稱,就會(huì)發(fā)生一個(gè)錯(cuò)誤。


  析構(gòu)函數(shù)聲明的主體指定了為了對(duì)類的新實(shí)例進(jìn)行初始化而執(zhí)行的語(yǔ)句。這于一個(gè)有void返回類型的實(shí)例方法的主體相關(guān)。

  例子

class Test
{
 static void Main() {
  A.F();
  B.F();
 }
}
class A
{
 static A() {
  Console.WriteLine("Init A");
 }
 public static void F() {
  Console.WriteLine("A.F");
 }
}
class B
{
 static B() {
  Console.WriteLine("Init B");
 }
 public static void F() {
  Console.WriteLine("B.F");
 }
}

  會(huì)產(chǎn)生或者是下面的輸出:

Init A
A.F
Init B
B.F

  或者是下面的輸出:

Init B
Init A
A.F
B.F


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 彭水| 迁西县| 潮州市| 乾安县| 称多县| 高碑店市| 右玉县| 伊宁县| 孟州市| 界首市| 西藏| 盘山县| 沙坪坝区| 通榆县| 驻马店市| 陆良县| 罗城| 都安| 神木县| 娱乐| 霍林郭勒市| 寻甸| 九江县| 太康县| 麦盖提县| 桑日县| 松桃| 新蔡县| 福贡县| 苍南县| 天津市| 常宁市| 西盟| 满洲里市| 北流市| 广安市| 洛隆县| 海阳市| 会宁县| 布尔津县| 青海省|