日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

十七 关于委托

發布時間:2025/6/17 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 十七 关于委托 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

先看委托。 然后事件 當然可恥的直接用了書的源碼。

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

function a(func) {var el= document.body;func(el) } function b(el) { do something.. } a(b);

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

internal delegate void Feedback(Int32 value); 先定義
public static void Main()
{
   Counter(
1, 3, new Feedback(FeedbackToConsole)); //這是調用... 同樣是將方法傳入
  
//Counter(1, 3, Program.FeedbackToConsole); //這樣也是可以的
}

private
static void Counter(Int32 from, Int32 to, Feedback fb)
{
for (Int32 val = from; val <= to; val++)
{
if (fb != null)
fb(val);
}
}

private static void FeedbackToConsole(Int32 value)
{
Console.WriteLine(
"Item=" + value);
}

關于協變 逆變

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

逆變 就是返回基類..

當然 他們只能針對值類型

internal delegate?object?Feedback(Int32 value);?

你綁定的方法可以是 string aaa(int i);

不過關于協變逆變的性能以后再討論


前面調用的都是靜態方法,這里傳了一個實例,當然只是把棧中得地址傳了過去

private static void InstanceDelegateDemo()
{
Program p = new Program();
Counter(
1, 3, new Feedback(p.FeedbackToFile)); //這里傳遞的是引用..
Console.WriteLine();
}

  

關于寫法. 委托從1.0到現在寫法有一些變化..

internal delegate void Feedback(Int32 value);

public static void Main() {
Counter(1, 3, new Feedback(FeedbackToMsgBox)); 1.0 Counter(1, 3, delegate(int a) 2.0 { //匿名方法   //你不必單獨創建方法 就像上面的FeedbackToMsgBox,當然這玩意兒得建立在你只在這里使用   //感覺上就像閉包. 當然前提是他得引用上下文..   //當然簡便代碼是很重要的,很多時候調用方法需要傳入一個委托, 沒有他你就麻煩了。。   //也有缺點。 畢竟像過多外部參數 維護起來 啊哈 });

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 specialname rtspecialname instance void .ctor(object 'object', native int 'method') runtime managed
{
}
.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, new Feedback(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








轉載于:https://www.cnblogs.com/CallMeTommy/archive/2011/08/28/2148662.html

總結

以上是生活随笔為你收集整理的十七 关于委托的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。