C# 委託

來源:互聯網
上載者:User

標籤:建構函式   第一個   編譯   返回   轉換   div   where   winform   []   

學習C#的WinForm編程需要涉及到事件(Event),學習事件又要涉及到委託(Delegate)。最開始事件和委託的文法相當困擾我,最後發現委託相當於類型,事件相當於執行個體。

delegate關鍵字定義了一個類,派生自System.MulticastDelegate類,而MulticaseDelegate類又派生自System.MulticaseDelegate類。儘管委託類在文法上很奇怪,但是不能否認委託仍然屬於物件導向的範疇,委託仍是一個類,只能說明C#增加了快捷使用委託的文法糖。

int x = 40;GetAString firstStringMethod = new GetAString(x.ToString);Console.WriteLine("String is {0}", firstStringMethod());

委託的執行個體是一個方法地址,既可以是執行個體方法,也可以是靜態方法。方法名稱後面帶圓括弧表示方法的調用,不帶圓括弧表示方法的地址。

 

關於 委託推斷(delegate inference)

委託推斷可以說是 C# 2.0 增加的一個文法糖。將一個方法的地址傳送給一個委託變數,編譯器會自動檢測委託變數的委託類型,然後根據委託類型建立委託執行個體,並把方法地址傳送給委託的建構函式。

GetAString firstStringMethod = new GetAString(x.ToString);
GetAString firstStringMethod = x.ToString;

說到這裡,委託的調用其實也是一個文法糖。委託的本質還是一個類,實現一個委託的執行個體也就是實現一個類的執行個體,只不過委託的執行個體只能調用經過定義後固定的方法。

GetAString firstStringMethod = new GetAString(x.ToString);firstStringMethod();
GetAString firstStringMethod = new GetAString(x.ToString);firstStringMethod.Invoke();

 

 

關於 泛型委派 Action<T> 和 Func<T>

先說泛型,C# 2.0 加入的泛型解決了兩個問題。

第一個是避免了“根據不同的參數類型,去定義不同的方法簽名”,即“泛型是個筐,啥都往裡裝”。泛型作為一個開放的資料類型,根據方法調用時的實參的值轉換成對應的方法簽名,這個過程在編譯時間就可以實現和錯誤修正。即,泛型實現了代碼中同一個方法多個入參實現的不同版本,在編譯時間可以根據需要分成多個入參類型的不同版本,假如是初級的編譯實現方法的話。

第二個是避免了實值型別和參考型別之間轉換時,所需要的裝箱(boxing)和拆箱(unboxing)的開銷。在我所設想的泛型編譯實現的方法中,最簡單的辦法莫過於根據泛型參數方法的調用,實現此方法在具體參數類型下的不同版本,即通過編譯器實現多個需要的版本,減少代碼編寫的工作量。

說到底,如果泛型沒有特別的編譯實現原理的話,就是一個協助開發人員減少代碼量的文法糖。不指定具體的參數類型,根據 where 關鍵字限定參數類型應符合的介面,在編譯時間根據方法的調用情況具體實現。這樣看來泛型和隱式類型一樣,即減少了開發人員的工作,又再編譯時間指定或推斷出了具體的參數類型,C#仍然是型別安全的強型別語言。

 

那麼 Action<T> 和 Func<T> 呢,在減少開發人員工作的道路上更近了一步。物件導向語言大多需要類型的聲明、類型的實現、類型的調用這三個步驟。委託作為一個類,也需要先定義再使用。那麼通過預定義的Action<T>和Func<T>委託,就免去了委託定義的步驟,同時通過泛型的實現,就囊括了常見的大部分委託。委託的定義本來就是指定參數的數量和各自類型,以及傳回值的類型,Action<T>和Func<T>一步實現了委託的定義和調用。

delegate double DoubleOp(double x);static void Main() {    DoubleOp[] operations = {        MathOperations.MultiplyByTwo,        MathOperations.Square    };}
static void Main() {    Func<double, double>[] operations = {        MathOperations.MultiplyByTwo,        MathOperations.Square        };}

關於Action<T>和Func<T>還有另一個問題。泛型委派可以實現隨用隨寫,不必提前定義。同時由於沒有定義委託名稱,各泛型型別之間沒有邏輯關聯。這樣的話使用起來,定義委託相比泛型委派,擁有全域定義的意義,類似於全域變數的意義,只不過由於委託定義了方法的簽名,委託一經使用就不可以再更改全域的定義。而泛型委派相比定義委託,調用時即可獲知委託變數的方法簽名,使用起來更直接,不必查詢委託的定義。如果沒有效能方面的考慮,當然我也考慮不到,我更願意使用泛型委派,即Action<T>和Func<T>。

static void ProcessAndDisplayNumber(DoubleOp action, double value) {    double result = action(value);    Console.WriteLine("Value is {0}, result of operation is {1}", value, result);        }
static void ProcessAndDisplayNumber(Func<double, double> action, double value) {    double result = action(value);    Console.WriteLine("Value is {0}, result of operation is {1}", value, result);}

 

關於 多播委託

關於多播委託我暫時沒啥好說的。

 

參考資料:《Professional C# 4 and .NET 4》

C# 委託

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.