委託

忽然發現以前的不少觀念都不對的,關於編程,關於c#,我認爲有須要實現了就成了,結果重要,過程不重要,雖然不少時候你們都講擴展性、易用性等軟件思想,可是在實際應用中,這些基本上都是空話,因此像c#中的委託、類、事件、多線程並無深刻了解,是時候把這塊東西深刻了解了解了html

委託編程

一、在C#中,全部的委託都是從System.Delegate類派生的。 c#

二、委託隱含具備sealed屬性,即不能用來派生新的類型。安全

三、委託最大的做用就是爲類的事件綁定事件處理程序。多線程

四、在經過委託調用函數前,必須先檢查委託是否爲空(null),若非空,才能調用函數。異步

五、在委託實例中能夠封裝靜態的方法也能夠封裝實例方法。函數

六、在建立委託實例時,須要傳遞將要映射的方法或其餘委託實例以指明委託將要封裝的函數原型(.NET中稱爲方法簽名:signature)。注意,若是映射的是靜態方法,傳遞的參數應該是類名.方法名,若是映射的是實例方法,傳遞的參數應該是實例名.方法名。spa

七、只有當兩個委託實例所映射的方法以及該方法所屬的對象都相同時,才認爲它們是想等的(從函數地址考慮)。線程

委託是C#中的一種引用類型,相似於C/C++中的函數指針。與函數指針不一樣的是,委託是面向對象、類型安全的,並且委託能夠引用靜態方法和實例方法,而函數指針只能引用靜態函數。委託主要用於 .NET Framework 中的事件處理程序和回調函數。 一個委託能夠看做一個特殊的類,於是它的定義能夠像常規類同樣放在一樣的位置。與其餘類同樣,委託必須先定義之後,再實例化。與類不一樣的是,實例化的委託沒有與之相應的術語(類的實例化稱做對象),做爲區分咱們將實例化的委託稱爲委託實例。 指針

函數指針 

  一個函數在編譯時被分配給一個入口地址,這個入口地址就稱爲函數的指針,正如同指針是一個變量的地址同樣。

  函數指針的用途不少,最經常使用的用途之一是把指針做爲參數傳遞到其餘函數。咱們能夠參考下面的例子進一步理解函數指針做爲參數的狀況:
# include 
   
  int max(int x,int y) 

  { 

      return (x>y?x:y); 

  } 

  int min(int x,int y) 

  { 

     return(x<y?x:y); 
  } 
   
  int sub(int x, int y) 
   
  { 
   
    return(x+y); 
   
  } 

  int minus(int x,int y) 

  {  

    return(x-y); 

  } 

  void test(int (*p)(int,int),int (*q)(int,int),int a,int b) 

  { 

    int Int1,Int2; 

    Int1=(*p)(a,b); 

    Int2=(*q)(a,b); 

    printf("%d,\t%d\n",Int1,Int2); 

  } 

  void main() 

  { 

    test(max,min,10,3); 
     
    test(sub,minus,10,3); 

  } 
客觀的講,使用函數指針做爲其參數的函數若是直接調用函數或是直接把調用的函數的函數體放在這個主函數中也能夠實現其功能。那麼爲何還要使用函數指針呢?咱們仔細看一下上面的main()函數就能夠發現,
main()函數兩次調用了test函數,前一次求出最大最小值,後一次求出兩數的和與差。若是咱們test函數不用函數指針,而是採用直接在test函數中調用函數的方法,使用一個test函數還能完成這個功能嗎?顯然
不行,咱們必須寫兩個這樣的test函數供main()函數調用,雖然大多數代碼仍是同樣的,僅僅是調用的函數名不同。
上面僅僅是一個簡單的例子,實際生活中也許main()函數會頻繁的調用test(),而每次的差異僅僅是完成的功能不同,也許第一次調用會要求求出兩數的和與差,而下一次會要求求出最大值以及兩數之和,第三次呢,
也許是最小值和最大值,……,若是不用函數指針,咱們須要寫多少個這樣的test()函數?顯然,函數指針爲咱們的編程提供了靈活性。
另外,有些地方必須使用到函數指針才能完成給定的任務,特別是異步操做的回調和其餘須要匿名回調的結構。另外,像線程的執行,事件的處理,若是缺乏了函數指針的支持也是很難完成的。
類型安全
從上面的介紹能夠看出,函數指針的提出仍是有其必要的,上面的介紹也同時說明了委託存在的必要性。那麼爲何C#中不直接用函數指針,而是要使用委託呢?這就涉及到另一個問題:C#是類型安全的語言。
何謂類型安全?這裏的類型安全特指內存類型安全,即類型安全代碼只訪問被受權能夠訪問的內存位置。 若是代碼以任意偏移量訪問內存,該偏移量超出了屬於該對象的公開字段的內存範圍,則它就不是類型安全的代碼。
顯然指針不屬於類型安全代碼,這也是爲何C#使用指針時必須申明unsafe的緣故。 那麼類型不安全代碼可能會帶來什麼不良的後果呢?相信對於安全技術感興趣的朋友必定十分熟悉緩衝區溢出問題,經過緩衝區溢出攻
擊者能夠運行非法的程序得到必定的權限從而攻擊系統或是直接運行惡意代碼危害系統,在UNIX下這是一個十分廣泛的問題。那麼緩衝區溢出又和函數指針有什麼關係呢?事實上,攻擊者就是經過緩衝區溢出改變返回地址
的值到惡意代碼地址來執行惡意代碼的。咱們能夠看看下面的代碼:
void copy() 
  { 
  char buffer[128]; 
  ........ 
  strcpy (buffer,getenv("HOME"));//HOME爲UNIX系統中的HOME環境變量 
  ........ 
  } 
上面的代碼中若是HOME環境變量的字符數大於128,就會產生緩衝區溢出,假如這個緩衝區以前有另外一個函數的返回地址,那麼這一是地址就有可能覆蓋,而覆蓋這一地址的字符有可能就是惡意代碼的地址,攻擊者就有可能
攻擊成功了!
  
上面的例子僅僅是指針問題中的一種,除此之外,還可能因爲錯誤的管理地址,將數據寫入錯誤地址,形成程序的崩潰;還可能因爲對指針不恰當的賦值操做產生懸浮指針;還可能產生內存越界,內存泄漏等等問題。
  
因而可知,指針不是類型安全的,函數指針固然也不例外,因此C#裏面沒有使用函數指針,並且不建議使用指針變量。
  
委託
  
前面的說明充分證實了委託存在的必要性,那麼咱們再談談爲何委託是類型安全的。C#中的委託和指針不同,指針不經過MSIL而是直接和內存打交道,這也是指針不安全的緣由所在,固然也是採用指針可以提升程序
運行速度的緣故;委託不與內存打交道,而是把這一工做交給CLR去完成。CLR沒法阻止將不安全的代碼調用到本機(非託管)代碼中或執行惡意操做。然而當代碼是類型安全時,CLR的安全性強制機制確保代碼不會訪問本
機代碼,除非它有訪問本機代碼的權限。 委託派生於基類System.Delegate,不過委託的定義和常規類的定義方法不太同樣。委託的定義經過關鍵字delegate來定義:

public delegate int myDelegate(int x,int y); 
上面的代碼定義了一個新委託,它能夠封裝任何返回爲int,帶有兩個int類型參數的方法。任何一個方法不管是實例方法仍是靜態方法,只要他們的簽名(參數類型在一個方法中的順序)和定義的委託是同樣的,
均可以把他們封裝到委託中去。這種簽名方法正是保證委託是類型安全的手段之一。
產生委託實例和產生類實例(對象)差很少,假如咱們有以下的方法: 
public int sub(int x,int y) 
{   
  return(x+y); 
} 
咱們就可使用以下的代碼獲得一個委託實例:
myDelegate calculatin=new myDelegate(sub); 
接下來咱們就能夠直接使用calculation調用sub方法了:
calculation(10,3); 
 下面咱們將用委託重寫上面的一個程序來看一下在C#中如何經過委託實現由函數指針實現的功能: 
using System;  
  class MathClass
  { 
      public static int max(int a,int b) 
      { 
          return(a>b?a:b);  
      } 
   
      public static int min(int a,int b) 
      { 
           return(a<b?a:b);  
      } 
   
      public static int sub(int a,int b) 
      { 
         return (a+b); 
       } 
   
      public static int minus(int a,int b)   
      {  
          return (a-b);   
      } 
  } 
   
  class Handler   
  { 
   
      private delegate int Calculation(int a, int b); 
   
      private static Calculation[] myCalculation=new Calculation[2]; 
   
      public static void EventHandler(int i,int a,int b)
    }
            

 博客園裏面有不少文章關於委託的,我看到比較好,比較全的是:http://www.cnblogs.com/kirinboy/archive/2009/08/26/intensive-delegate-1.html

相關文章
相關標籤/搜索