程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 用 JavaScript 的匿名函數理解 C# 的委托

用 JavaScript 的匿名函數理解 C# 的委托

編輯:C#入門知識

 

我的腦子裡有個名詞一直在糾結:委托。

顧名思義,委托,把事情托付給他人或機構(辦理)。造句諸如:“當事人委托律師出庭辯護”,“我能委托你辦一件事嗎”。 很明顯,委托是個抽象動作(Action),目的具體不詳,“出庭辯護”,“辦一件事”才是真正要做的事。但C#中委托卻讓我之前一頭霧水,因為這個概念從來未有如此被擺上台面。

我確信在以往的JavaScript 編程中,有類似“委托”這個概念的,比如按鈕事件綁定,匿名函數。而網上搜羅有關C# 委托的言語也大多與函數指針、事件綁定有關。下面將用JavaScript 與C# 兩種“委托”相對比,用於加深理解。

先看JavaScript中,給按鈕定義事件的方法:

 1 <input type="button" value="Hello" id="btn" />

 2 <script type="text/javascript">

 3 //方法一:

 4 function SayHello()

 5 {

 6   alert("Hello world!");

 7 }

 8 document.getElementById("btn").attachEvent("onclick", SayHello);

 9

10 //方法二,匿名函數

11 document.getElementById("btn").attachEvent("onclick", function(){alert("Hello world")});

12 </script>

方法一是把一個現有的函數引用(類指針)賦值給按鈕的事件,而方法二是在給按鈕定義事件時,就地定義一個匿名函數。這兩種方法其實是一致的,如果把SayHello 的定義方式換用另外一種方式,將會發現,這一切不過是代碼的游戲:

var SayHello = function(){alert("Hello world!")};

方法一與方法二不過是引用上面代碼等號的左邊與右邊而已!

再看看C#:

1 protected void Page_Load(object sender, EventArgs e)

2     {

3         btn.Click += new System.EventHandler(btn_Click);           

4     }

5

6     void btn_Click(object sender, EventArgs e)

7     {

8         //do sth

9     }

這是眾所熟悉的代碼,btn 是頁面上的一個按鈕,+= 表示在原有的基礎上續加一個事件,這與IE下的attachEvent(FF下的addEventLisener) 同出一轍。System.EventHandler 實際上就是一個委托,通過ILSpy 查看這個類:

 1 using System;

 2 using System.Runtime.InteropServices;

 3 namespace System

 4 {

 5     [ComVisible(true)]

 6     [Serializable]

 7     public delegate void EventHandler(object sender, EventArgs e);

 8 }

 9

10 //構造函數:

11 // System.EventHandler

12 public extern EventHandler(object @object, IntPtr method);

因此,給按鈕增加事件,是先創建一個委托,委托再指定需要調用的函數(如btn_Click)。

通過對比兩種語言在以上事件定義實例上,C# 非常細致地抽象出這個動作,把委托與事件函數區分開來,這是JavaScript比較模糊的地方(或稱為JS的靈活性?)。

再看另外一種場合,JQuery 可以這樣遍歷數組:

 1 <script type="text/javascript">

 2 function DoSth(obj, i)

 3 {

 4    /*do sth*/

 5 }

 6 $("#box ul li").each(DoSth);

 7

 8 //或者這樣:

 9 $("#box ul li").each(function(obj, i){/*do sth*/});

10 </script>

以上代碼的$() 函數返回的是元素數組,echo 方法的作用是遍歷並處理此數組。那它是怎樣做這樣的效果呢? 它把另外一個函數(假設為函數DoSth)當作參數,傳到echo 內部,所有處理動作都由函數DoSth來完成,並且默認規定好了接口,函數DoSth只能接收兩個參數,第一個是數組中的元素(弱類型),第二個是整型計數器。

把一個函數當地另外一個函數的參數,這樣的案例在原生的JavaScript 還有如:replace(/re/, function($1){}),array.sort(function(x){}),用法一致,不再討論。

再看看C#:

 1 protected void Page_Load(object sender, EventArgs e)

 2     {

 3         List<string> Arr = new List<string>() { "2011年","10月","22日"};

 4         //方法一

 5         Arr.ForEach(delegate(string txt)

 6         {

 7             Write(txt);

 8         });

 9

10         //方法二

11         Arr.ForEach(new Action<string>(Write));

12

13         //方法三

14         Arr.ForEach(Write);

15     }

16

17

18 private void Write(string txt)

19     {

20         Response.Write(txt);

21     }

上面的代碼與JavaScript 何其相似。方法一就地定義委托,並定義委托的實際內容。方法二采用C#3.0的Action<T> 委托,它是delegate 類的泛型重載。方法三是編譯器給我們提供的便利,它是方法二的簡寫。

行文至此,委托的概念頓時明晰,混沌的思維豁然開朗,揭開面紗,原來早已熟悉多時,猛拍腦門,狠掐大腿......

 

 

作者:阿蔡

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved