<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 原則24:使用委托來表達回調 **By D.S.Qiu** **尊重他人的勞動,支持原創,轉載請注明出處:[http://dsqiu.iteye.com](http://dsqiu.iteye.com)** 我:“兒子,到院子去除草。要去看會書。” Scott:“爸爸,我清理好院子了。” Scott:“爸爸,我已經把草放在除草機上了。” Scott:“爸爸,除草機不能啟動。” 我:“讓我來啟動它。” Scott:“爸爸,我已經做完了。” 這個簡單的交互展示了回調。我給兒子一個任務,它(重復)報告他的狀態以打斷我。而當我在等待他完成任務的每一個部份時,我不用阻塞我自己的進程。他可以在有重要(或者事件)狀態報告時或者向我詢求幫助時,可以定時的打斷我,。回調就是用于異步的提供服務器與客戶之間的信息反饋。它們可能在多線程中,或者可能是簡單的提供一個同步更新點。在 C# 語言里是用委托來表達回調的。 委托提供類型安全的回調定義。雖然大多數是作為事件使用,那不是 C# 語言唯一使用這個特性的地方。任何時候,如果你想在兩個類之間進行通信,而你又期望比使用接口有更少的偶合性,那么委托是你正確的選擇。委托可以讓你在運行時確定目標并且通知用戶。委托就是包含了某些方法的引用的對象。這些方法可以是靜態方法,也可以是實例方法。使用委托,你可以在運行時確定與一個或者多個客戶對象進行交互。 回調和委托是 C# 語言常見的習慣,組合 lambda 表達式語法的以表達委托。此外,.NET 框架定義了許多常見的委托形式,如 Predicate&lt;T&gt; , Action&lt;&gt; 和 Func&lt;&gt; 。Predicate&lt;T&gt; 是測試條件的布爾函數。 Func&lt;&gt; 傳入多個參數并產生一個單一的結果。是的,這意味著 Func&lt;T,bool&gt; 和 Predicate&lt;T&gt; 是相同的形式。盡管編譯器不會將 Predicate&lt;T&gt; 和 Func&lt;T,bool&gt; 看做相同的。最后, Action&lt;&gt; 有多個參數并且有 void 的返回值類型。 LINQ 就是由這些概念構建出來的。 List&lt;T&gt; 類也包含很多使用回調的方法。看下面的代碼: ``` List<int> numbers = Enumerable.Range(1, 200).ToList(); var oddNumbers = numbers.Find(n => n % 2 == 1); var test = numbers.TrueForAll(n => n < 50); numbers.RemoveAll(n => n % 2 == 0); numbers.ForEach(item => Console.WriteLine(item)); ``` Find() 方法傳入一個委托,形式為 Predicate&lt;int&gt; 以檢查隊列中的每個元素。它是很簡單的回調。 Find() 方法使用回調對每個元素進行檢查,并且返回通過謂詞測試的元素。編譯器會將 lambda 表達式,轉換為委托,并使用委托表達回調。 TrueForAll() 同樣它檢查每個元素,而且返回謂詞為 true 的項。 RemoveAll() 移除那些謂詞為 true 的項以修改隊列。 最后, List.ForEach() 方法對隊列的元素執行指定的動作。和前面一樣,編譯器轉換 lambda 表示為方法并創建委托引用這個方法。 你會在 .NET 框架中發現很多這樣的例子。所有 LINQ 都是構建與委托之上的。回調函數是用來處理在 WPF 和 Window Form 上的多線程編程。.NET 框架需要很簡單方法的地方,它會使用委托,即調用者可以用 lambda 表達式來表達。當你需要在 API 中需要回調約定可以遵循這個例子的做法。 由于歷史原因,所有委托都是多播委托。多播委托會一次調用所有添加的目標函數。有兩點需要注意的:如果有異常是不安全的,而且最后執行的目標函數的返回值會作為回調的返回值。 在多播委托調用的內部,每個目標對象會被連續調用。委托不捕捉任何異常。因此,任何異常的拋出將終止委托鏈的調用。 返回值存在一個相似的問題。你可以定義委托有返回類型不是 void 。你可以寫一個回調來檢查用戶中止: ``` public void LengthyOperation(Func<bool> pred) { foreach (ComplicatedClass cl in container) { cl.DoLengthyOperation(); // Check for user abort: if (false == pred()) return; } } ``` 單一委托是可以正常工作的,但是對于多播是有問題的: ``` Func<bool> cp = () => CheckWithUser(); cp += () => CheckWithSystem(); c.LengthyOperation(cp); ``` 委托調用的返回值是多播鏈最后一個函數調用的返回值。所有其他返回值都會被忽略。CHeckWithUser() 位置的返回值是會被忽略的。 你可以通過自己調用目標委托解決這個問題。每個創建的委托包含一個委托隊列。自己檢查這個隊列并遍歷調用: ``` public void LengthyOperation2(Func<bool> pred) { bool bContinue = true; foreach (ComplicatedClass cl in container) { cl.DoLengthyOperation(); foreach (Func<bool> pr in pred.GetInvocationList()) bContinue &= pr(); if (!bContinue) return; } } ``` 在這個例子,我已經定義了每個委托返回值必須是 true 才會繼續執行的語義。 委托提供在運行時利用回調的最好方式,滿足簡單的客戶類上的需求。你可以在運行時確定委托目標。你可以支持多個回調目標。客戶端回調需要使用 .NET 的委托實現。 小結: 使用委托來表達回調。 歡迎各種不爽,各種噴,寫這個純屬個人愛好,秉持”分享“之德! 有關本書的其他章節翻譯請[點擊查看](/category/297763),轉載請注明出處,尊重原創! 如果您對D.S.Qiu有任何建議或意見可以在文章后面評論,或者發郵件(gd.s.qiu@gmail.com)交流,您的鼓勵和支持是我前進的動力,希望能有更多更好的分享。 轉載請在**文首**注明出處:[http://dsqiu.iteye.com/blog/2083564](/blog/2083564) 更多精彩請關注D.S.Qiu的博客和微博(ID:靜水逐風)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看