十七 關於委託

2022-02-16 13:09:50 字數 4807 閱讀 4273

先看委託。 然後事件 當然可恥的直接用了書的原始碼。

首先.. 委託就和js中得**一樣,別人都用c舉例...本人只能用js舉例。。。。 ╮(╯▽╰)╭

function a(func)

function b(el)

a(b);

委託也是這樣.. 不過要麻煩很多.

internal

delegate

void

feedback(int32 value); 先定義

public

static

void

main()

private

static

void

counter(int32 from, int32 to, feedback fb)

}private

static

void

feedbacktoconsole(int32 value)

關於協變 逆變

協變 就是委託返回的型別是派生類

逆變 就是返回基類..

當然 他們只能針對值型別

internal

delegate

object

feedback(int32 value); 

你繫結的方法可以是 string aaa(int i);

不過關於協變逆變的效能以後再討論

前面呼叫的都是靜態方法,這裡傳了乙個例項,當然只是把棧中得位址傳了過去

private

static

void

instancedelegatedemo()

關於寫法. 委託從1.0到現在寫法有一些變化..

internal

delegate

void

feedback(int32 value);

public static void main()

);

counter(1,3, a => a++); 3.5

//貌似生成的**是乙個匿名方法 攤手..

//適當的使用委託(包括 匿名方法,lamb), 能讓**更優美~~~~~~~~~

}
private

static

void

counter(int32 from, int32 to, feedback fb){}

關於他裡面幹了什麼?

首先看il.. 雖然看的惱火

internal delegate void feedback(int32 value);

.

class

auto ansi

sealed

nested assembly feedback

extends [mscorlib]system.multicastdelegate

.method

public

hidebysig newslot

virtual

instance

class

[mscorlib]system.iasyncresult begininvoke(int32

'value',

class

[mscorlib]system.asynccallback callback,

object

'object

') runtime managed

.method

public

hidebysig newslot

virtual

instance

void

endinvoke(

class

[mscorlib]system.iasyncresult result) runtime managed

.method

public

hidebysig newslot

virtual

instance

void

invoke(int32

'value

') runtime managed

}

繼承自 system.multicastdelegate

第乙個是乙個構造

所有委託都有構造器,引數乙個是 

object

乙個是int

開始我以為是傳得引數,畢竟委託的引數也是int,後來重新寫了乙個 string引數的委託,發現構造的引數還是int。 憂鬱。

object是引用物件(引發裝箱拆箱

?),如果傳入的是靜態方法 object 會是null

int 據書上說是 標識了方法的乙個特殊值...

然後 在構造器內部

object

和 int 分別儲存在_target _methouptr

然後乙個和原型一樣的方法

這玩意就是呼叫原方法的方法.. 委託都會隱式的呼叫他.

然後就是三個變數

之前上面提到了

_target 

//如果你傳入的不是靜態方法, 那這個就存放你傳進來的方法所屬的類

_methouptr

//只是乙個整數值,標示**的方法

_invocationlist

//陣列. 通常是null 只有在委託鏈的時候

關於委託鏈

console.writeline(

"----- chain delegate demo 1 -----");

feedback fb1

=new

feedback(feedbacktoconsole);

feedback fb2

=new

feedback(feedbacktomsgbox);

feedback fb3

=new

feedback(p.feedbacktofile);

feedback fbchain

=null

;fbchain

=(feedback)delegate.combine(fbchain, fb1);

fbchain

=(feedback)delegate.combine(fbchain, fb2);

fbchain

=(feedback)delegate.combine(fbchain, fb3);

counter(1,

2, fbchain);

console.writeline();

fbchain

=(feedback)delegate.remove(fbchain,

newfeedback(feedbacktomsgbox));

counter(1,

2, fbchain);

書上的例子很明確了

在新增的時候

_invocationlist

[0,1,2] 分別代表的3個委託,所以在 counter執行的時候 會分別呼叫那3個委託

同樣 也提供了remove 刪除不用的

當然也有簡便方法

fbchain += fb1;

fbchain += fb2;

fbchain += fb3;

fbchain.getinvocationlist(); 返回delegate over~

泛型委託

internal

delegate

void

feedback(t value); //只是乙個t~ 其他不變

關於泛型這裡就不贅述了 會在之後的寫 到時候再反過來加鏈結吧

ok 談談委託的使用

其實都知道 委託在很多程度上可以用 介面來代替, 只是每次都弄個類 搞個介面 確實比較繁瑣

委託給人的感覺就是不知道使用者要幹什麼,如果上下文清楚 個人感覺使用介面要好一點(當然,這對我來說只是規範問題)

其實這裡還差一段**... 就是測試 委託 和 介面..  在處理相同的時候的效率問題

本人思來想去 還是覺得自己的測試方法不太好, 暫時擱置一下吧. 想到了再說

ok 之前是我的觀點.

還有一種觀點就是,這些效能損失在實際**中是微乎其微的.

而是應該在效能和可讀性,可維護性上找到乙個平衡點

不可否認 lamb表示式的正確使用確實讓**易懂和優美。

a.select(lamb)

.where(lamb

) .orderby(

lamb

).tolist();

當你使用它的時候有些東西需要注意

1. 這一連串的方法,他當時不會執行,只會在你呼叫的時候才會執行~

2. 他是迴圈執行的 第乙個元素 select - where - select - orderby - 第二個元素 重複..

3. 就是他得延遲性

(這玩意兒..我沒有研究)

有興趣的可以去看看 姐夫趙的 從.net中委託寫法的演變談開去(下):效能相關

特別是在使用官方提供的方法的時候,lamb的優勢極其明顯

當然也有缺點 比如除錯,lamb表示式無法除錯,所以建議在lamb表示式中不要有複雜邏輯,要不然除錯起來夠你折騰

over

(十七)關於宣告

在我們需要使用乙個變數的時候,我們會這麼做 int a 這段話,便是乙個宣告,宣告a是乙個整數變數。如果沒有宣告,那麼就在之後說 cout 之所以這樣,是因為不宣告便直接使用,很容易導致因為拼寫錯誤,導致創造出乙個新的變數,而你很難發現問題到底出現在哪。例如cammon camnon cammon ...

關於Predicate委託

關於predicate委託 predicate委託在.net類類庫中經常出現,此委託的定義如下 public delegatebool predicate t obj 從其定義可以看到,此委託引用乙個返回bool 值的方法,在實際開發中,通常使用predicate委託變數引用乙個 判斷條件函式 在判...

關於事件委託

首先,先來看乙個例子 如微博,每一條博文都有事件,如增加 刪除等!這樣子的話我們每次發微博的時候就得在建立的時候把該有的事件給加上。html js var otext document.getelementbyid txt1 var obtn document.getelementbyid btn1...