国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

面試中可能會被問到的幾個關于“委托”的問題

2019-11-14 16:35:43
字體:
來源:轉載
供稿:網友

 

  這幾天比較清閑,剛好前段時間買了本CLR Via C#,在.Net界大家都知道Jeffrey大師的這本經典著作,慚愧一直沒有拜讀。

不過在C#著作中經典的非常多。讀書的那時候就是通過《C#與.NET 3.0高級程序設計》這本書接觸C#的,也被稱為C#圣經。

CLR Via C#中的委托說的非常好,比較深入,讓人耳目一新,回味無窮的感覺,看這本書的時候一定要記得帶上ILDasm和

Reflector,有了他們就可以讓我們更加深入的看一些問題,讀書的方式有很多種,提問式的,提煉式的,因為任何東西都遵循

“八二原則“,100個字中,有營養的文字也就區區20個而已,抓住了就理解了,好了,就亂扯到這里了。

 

Q: 什么是委托

 

A: 委托就是一個繼承自MulticastDelegate的類,不信可以用 ILdasm 看一下。

1   public delegate void FlyAction();

 

Q: 我從ILdasm中看到了Invoke方法,但是我在Delegate卻沒有看到該方法的定義?為什么?

 

A: 這其實是混淆了delegate關鍵字和FCL中的Delegate類型,而對于delegate關鍵字,編譯器和CLR給我們做了很多的優化,

    并且掩蓋了很多復雜的細節,而FCL中的Delegate并沒有。

 

Q: 我知道可以將方法作為參數傳遞給委托,然后可以在任何地方通過委托的invoke來執行那個作為參數的方法,請問是如何做到的?

 

A:既然可以在任何地方引用這個參數的方法,那就要看看方法是如何入侵到委托的。

   ①  先看看實例代碼:

 1  namespace Demo 2  { 3      class PRogram 4      { 5          public delegate void FlyAction(); 6   7          static void Main(string[] args) 8          { 9              Bird bird = new Bird();10  11              FlyAction action = new FlyAction(bird.Fly);12  13              action.Invoke();14          }15      }16  17      public class Bird18      {19          public static Random rand = new Random();20 21          public void Fly()22          {23              return "i can fly " + rand.Next();24          }25      }26  }

 

      從第一個QA中我們也看到了,其實委托是就是類,那我new一個類時,bird.fly其實就是類的構造函數的參數。

   ② 再來看看生成的IL中的構造函數。

 

   這時候問題就出來了,為什么這里有兩個參數,而new FlyAction(bird.Fly) 中卻是一個參數,這里貌似是有問題的,不符合語法規

   則,其實這里還是編譯器提供了一個中間層,通過這個中間層做了一個轉化,從而給我們隱藏了具體邏輯。其實在delegate中提供了

    一個Target和Method屬性,當我們傳入bird.Fly時,Target記錄了Bird這個類,Method記錄了Bird中的Fly方法,所以invoke的時

   候會自動觸發Bird類中的Fly方法。證據如下:

這里補充一點,當new FlyAction的時候如果是靜態方法,那么Target=null的,編譯器只需要通過Method就能找到觸發的方法。

 

Q:為什么在多播委托中,不建議回調方法有返回值,即使有返回值,多播中的方法也只能返回最后一個值,如果我想獲取每個方法

     的返回值,應該怎么處理? 實例代碼如下:

 1     class Program 2     { 3         public delegate string FlyAction(); 4  5         static void Main(string[] args) 6         { 7             Bird bird = new Bird(); 8  9             FlyAction action1 = new FlyAction(bird.Fly);10 11             FlyAction action2 = new FlyAction(bird.Fly);12 13             FlyAction action3 = new FlyAction(bird.Fly);14 15             action1 += action2;16 17             action1 += action3;18 19             Console.WriteLine(action1.Invoke());20 21             var result = action1.GetInvocationList();22 23             Console.Read();24         }25     }26 27     public class Bird28     {29         public static Random rand = new Random();30 31         public string Fly()32         {33             return "i can fly " + rand.Next();34         }35     }

 

A:  既然提到了“多播”,其實就是唬人了,內部源代碼里面就是維護了一個List,將“多播”中的方法都放入到List中,Invoke的時候,

     就循環遍歷下List來依次調用里面的方法,這就是為什么建議不要用“有返回值“的方法。

   

下面我們可以通過  GetInvocationList 來獲取這個list里面的方法。

 

 

然后我們再來看看這個GetInvocationList 里面的代碼是怎么寫的。

 

看到了this._invocationList和for循環,是不是有一種徹底明白的感覺,如果你想獲取每個方法的返回值,那只能通過

GetInvocationList拿出來后,自己手工處理了,只有這樣才能拿到“多播委托”中每個方法的返回值。

 

Q:請問下最后一個問題,問完就睡覺,請問委托可以動態創建嗎?

 

A:可以的。Delegate中提供了CreateDelegate方法,就是可以動態創建的,舉個例子你就知道了。

 1     class Program 2     { 3         public delegate string FlyAction(); 4  5         static void Main(string[] args) 6         { 7             Bird bird = new Bird(); 8  9             //找到類下的方法10             var method = typeof(Bird).GetMethod("Fly", BindingFlags.Instance | BindingFlags.Public);11 12             var mydelegate = (FlyAction)Delegate.CreateDelegate(typeof(FlyAction), bird, method);13 14             var result = mydelegate.Invoke();15         }16     }17 18     public class Bird19     {20         public string Fly()21         {22             return "i can fly " + new Random().Next();23         }24     }

 

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 罗源县| 外汇| 库尔勒市| 怀安县| 长春市| 辽源市| 沙河市| 巫溪县| 宁德市| 德昌县| 肇源县| 连城县| 安泽县| 彭水| 屏边| 化州市| 都昌县| 巴林右旗| 上杭县| 沙洋县| 衡南县| 高邑县| 白朗县| 濮阳市| 吴忠市| 舟曲县| 淄博市| 奉节县| 双流县| 曲松县| 台山市| 七台河市| 芦溪县| 耿马| 全南县| 定结县| 亳州市| 收藏| 孟连| 乌兰浩特市| 攀枝花市|