主頁 > .NET開發 > C#語法--委托,架構的血液

C#語法--委托,架構的血液

2020-09-21 07:01:31 .NET開發

委托的定義

什么是委托?

委托實際上是一種型別,是一種參考型別,

微軟用delegate關鍵字來宣告委托,delegate與int,string,double等關鍵字一樣,都是宣告用的,

下面先看下宣告代碼,這里宣告了兩個委托,

1 2 public delegate void TestDelegate(string message); public delegate int TestDelegate(MyType m, long num);

delegate既然是關鍵字,和int,string一樣,那么,為什么delegate后又跟了一個void或者int呢?

如果他們是同等地位的關鍵字,為什么可以一起使用呢?

很簡單,我們把delegate后面的 【void TestDelegate(string message)】理解為一個變數,是不是就清晰明了了一些,

我們把delegate關鍵字理解為,是用來專門來定義這種復雜的變數的,而這種復雜的變數可以包含一個回傳值和任意數目任意型別的傳入引數,

有沒有感覺,這個復雜的變數特別像一個函式的定義,

沒錯,官方定義,委托型別的宣告與方法簽名相似,所以,這個復雜變數,的確,書寫的方式就是與函式一樣,

那么,為什么這個宣告方式如此怪異呢,是因為,我們用delegate定義的變數,只能用函式賦值,賦值方式如下所示:

1 2 3 4 5 6 7 8 9 10 public delegate void TestDelegate(string message); public delegate long TestDelegate2(int m, long num); public static void Excute() {     TestDelegate2 td = Double; } static long Double(int m, long num) {     return m * num; }

委托的基本應用

學會了賦值以后,我開始使用委托,

委托的使用方式如下:

1 2 string result = td(51, 8); Console.WriteLine(result);

這里我們會發現,委托的使用方式與函式呼叫一樣,

沒錯,它們的確是一樣的,因為委托是用函式來賦值的,所以呼叫方式一樣也并不奇怪,不是嗎,

換一種說法,就是委托封裝了一個函式,

如果委托是封裝的函式,并且它又是參考型別,那么委托第一種常規的應用就浮現出來了,

那就是——參考型別的函式,

如果函式是參考型別,那么這個函式只要沒被記憶體回收,就可以被呼叫,如果是public函式或者是public static函式,那么它能跨越的東西就更多了,

比如可以跨類呼叫,跨程式集呼叫等等,而這種用法,就是委托的基本應用,

匿名委托的應用

匿名委托的官方介紹:在 2.0 之前的 C# 版本中,宣告委托的唯一方式是使用命名方法, C# 2.0 引入匿名方法,在 C# 3.0 及更高版本中,Lambda 運算式取代匿名方法作為撰寫行內代碼的首選方式,

看不懂沒關系,我們直接來學習使用,代碼如下:

1 2 3 4 5 6 delegate string anonymousDelegate(int m, long num); public static void Excute() {     anonymousDelegate ad = delegate (int m, long num) { return m.ToString() + num.ToString(); };//2.0時代的匿名委托     anonymousDelegate ad2 = (m, num) => { return m.ToString() + num.ToString(); };//3.0以后匿名委托 }

如代碼所示,匿名委托是Lambda運算式,不懂的同學就當它是有固定寫法即可,不用講什么道理,只要記住并應用即可,

匿名委托雖然減少了一點代碼,但還是要求我們自己去宣告委托,所有,還能再簡寫一點嗎?

答案當然是,可以的,

Action與Func

Action與Func是微軟為我們預先定義好了的,兩個委托變數,其中Action是不帶回傳值的委托,Func是帶回傳值的委托,

可以說,Action與Func完全包含了,我們日常使用所需的,全部的,委托變數,

也就是說,我們可以不用再去自己手動宣告委托了,

下面來看最簡單的Action與Func的定義:

1 2 Action a1 = () => { }; Func<int> f1 = () => { return 1; };//必須寫 return 1;

Action與Func是泛型委托,各支持16個入參變數,下面代碼為一個入參的定義,多引數以此類推,

1 2 Action<int> a1 = (i) =>  { }; Func<string,int> f1 = (str) => {  return 1;//必須寫 return 1; };

委托的執行緒應用

委托的執行緒應用是委托的第二種用法,分為執行緒使用委托,和委托的異步應用兩種,

我們先看執行緒使用委托,如下代碼所示,一個無入參匿名Action和一個無入參匿名Func,

1 2 3 4 5 Task taskAction = new Task(() => { });//無入參匿名Action taskAction.Start(); Task<int> taskFunc = new Task<int>(() => { return 1; });//無入參匿名Func taskFunc.Start(); int result= taskFunc.GetAwaiter().GetResult();//獲取執行緒回傳結果

我們能看到兩種委托應用,代碼都非常簡潔,

下面我們再來看委托的異步應用,首先看最簡單的異步呼叫,

1 2 3 4 5 6 7 8 9 10 Action action = new Action(() => { }); IAsyncResult result = action.BeginInvoke((iar) => { }, null);   Func<int> func = new Func<int>(() => { return 1; });  IAsyncResult resultfunc = func.BeginInvoke((iar) => {     var res = func.EndInvoke(iar); }, null);

這里我們使用委托的BeginInvoke方法來開啟執行緒,進行異步呼叫,如上面代碼所示,這里介紹了Action與Func的最基礎的異步應用,

委托,架構的血液

委托是架構的血液,如果系統中沒有委托,那代碼將堆疊到一起,比大力膠粘的都緊密,

就好比一碗湯面倒掉了所有的湯,只要它靜放一個陣子,就會變成一坨面球,讓你無從下嘴,

所以,委托是架構的血液,是框架的流暢的基石,

那么委托到底是如何流動的呢?

我們先從剛介紹過的委托的執行緒應用說起,

----------------------------------------------------------------------------------------------------

第一核心應用——隨手執行緒:

我們在做開發的時候,一定接觸過父類,父類是干什么的呢?父類通常是用來撰寫公共屬性和函式,方便子類呼叫的,

那我們的委托的第一個核心應用,就是父類的公共函式,執行緒隨手啟動,如何隨手開啟呢?

首先,我們創建父類代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class BaseDelegateSyntax {     public void AsyncLoad(Action action)     {       }     public void AsyncLoad(Action action, Action callback)     {         IAsyncResult result = action.BeginInvoke((iar) =>         {             callback();         }, null);     }     public void AsyncLoad<T>(Action<T> action, T para, Action callback)     {         IAsyncResult result = action.BeginInvoke(para, (iar) =>         {             callback();         }, null);     }     public void AsyncLoad<T, R>(Func<T, R> action, T para, Action<R> callback)     {         IAsyncResult result = action.BeginInvoke(para, (iar) =>         {             var res = action.EndInvoke(iar);             callback(res);         }, null);     } }

我們看到上面的代碼,父類中添加了四個異步委托的呼叫函式,接下來,我們就可以在繼承該類的子類中,隨手開啟執行緒了,

子類代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class ChildDelegateSyntax : BaseDelegateSyntax {     public void Excute()     {         //開啟異步方法         base.AsyncLoad(() => { });           //開啟異步方法,并且在異步結束后,觸發回呼方法         base.AsyncLoad(() => { },             ()=>             {                 //我是回呼方法             });           //開啟異步有入參的方法,傳遞引數,并且在異步結束后,觸發回呼方法         base.AsyncLoad<string>((s) => { },"Kiba518",            () =>            {                 //我是回呼方法            });           //開啟異步有入參的方法,傳遞字串引數Kiba518,之后回傳int型結果518,         //并且在異步結束后,觸發回呼方法,回呼函式中可以獲得結果518         base.AsyncLoad<string,int>((s) => {             return 518;         }, "Kiba518",            (result) =>            {                //我是回呼方法 result是回傳值518            });     } }

看了上面的父子類后,是否感覺委托讓我們繁雜的執行緒世界變簡潔了呢?

----------------------------------------------------------------------------------------------------

第二核心應用——穿越你的世界:

接下來,我們來看委托的第二種核心用法,穿越的應用,

這個應用,是最常見,也最普通的應用了,因為委托是參考型別,所以A類里定義的委托,可以在被記憶體回收之前,被其他類呼叫,

我們經常會在各種論壇看到有人發問,A頁面如何呼叫B頁面的屬性、方法、父頁面獲取子頁面的屬性、方法,或者子頁面獲取父頁面的屬性、方法,

其實,只要定義好委托,并將委托正確的傳遞,就可以實作穿越的呼叫了,

下面我們看下穿越應用的代碼,

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class FirstDelegateSyntax {     public FirstDelegateSyntax()     {         Console.WriteLine(" First 開始 "  );         SecondDelegateSyntax sds = new SecondDelegateSyntax(()=> {             Console.WriteLine(" First傳給Second委托被觸發 ");         });         sds.Excute();         Console.WriteLine(" First 結束 ");     } }   public class SecondDelegateSyntax {     public Action Action { get; set; }     public SecondDelegateSyntax(Action _action)     {         Console.WriteLine(" Second的建構式 ");         Action = _action;     }     public void Excute()     {         Console.WriteLine(" Second的Excute被觸發 ");         Action();     } }

我們可以看到,我們傳遞的委托,穿越了自身所屬的類,在SecondDelegateSyntax類中被觸發了,

運行結果如下:

第三核心應用——回呼函式:

世界上本沒有回呼函式,叫的人多了,也就有了,

請記住,所有的回呼函式,都是委托的穿越應用,所有的回呼函式;都是委托的穿越應用;所有的回呼函式,都是委托的穿越應用,

重要的話要講三遍,

因為委托是參考型別,所以可以被[址傳遞],函式是不可以被傳遞的,

當你傳遞函式的時候,其實是匿名傳遞了一個委托的地址,

結語

委托是我們最常用的語法,它將函式封裝成參考型別的變數,供其他單位呼叫,

因為委托的特質是參考型別,所以決定了委托是可以進行址傳遞,也就是說,委托是穿梭于我們系統代碼中的列車,

我們可以在列車上放很多很多東西,在需要的站點,叫停列車,并將托運的東西搬下來使用,

所以,理論上,只要我們利用好委托,就可以大量減少冗余的代碼,

但委托這種列車,是每個程式員都可以定義的,如果一個專案中有十個開發者,每個人都在定義委托,那么,就有可能出現定義了十個相同的委托的情況,這樣就出現了撞車的現象,

所以委托在使用的時候,盡量做到有序傳遞,即預先做好列車的行駛路線,讓委托按照路徑運行,盡量不要定義可以被任何單位呼叫的公共委托,

如果需要公共委托,可以采取反射的方式來呼叫,

后面我會繼續寫事件,訊息,反射等語法,敬請期待,

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/94886.html

標籤:C#

上一篇:C# read file to bytes,File.ReadAllFiles,File.Open(),BinaryReader

下一篇:C#中提示:當前背景關系中不存在名稱“ConfigurationManager”

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more