網站首頁 編程語言 正文
委托的概念
委托這個名字取的神乎其神的,但實質是函數式編程,把函數作為參數傳遞給另一個參數。對于C語言程序員來說,就是把函數指針當作參數傳遞給另一個函數。
唯一需要注意的是,C#畢竟是強類型語言,用于委托的函數,也相當于變成了一種可以被傳遞的變量,所以在創(chuàng)建以及調用之前,需要聲明其數據類型
delegate int Op(int a, int b);
這個委托是一種需要傳入兩個整型參數的函數,返回值也是整數。接下來對這個委托進行實例化,最終代碼如下
int add(int a, int b)
{
return a + b;
}
var addTest = new Op(add);
void calc(Op func, int a, int b)
{
Console.WriteLine($"func({a},{b})={func(a,b)}");
}
calc(addTest, 2, 3);
delegate int Op(int a, int b);
事先說明一下,本文所有代碼均在.Net6的頂級語句中實現,頂級語句需要把delegate聲明放在最下面。
其中,add是一個十分質樸的函數,沒什么可說的;addTest是一個內置了add了Op對象,其功能與add是相同的。
calc是一個以Op對象為參數的函數,在這個函數中,通過Op對象func,計算了另外兩個參數a和b。
最后,調用了calc函數,將addTest作為參數,實質上是計算了add(2,3),并打印了這個結果。
func(2,3)=5
>“調試停止時自動關閉控制臺”。
按任意鍵關閉此窗口. . .
多播委托
所謂多播委托,就是一個委托中通過+=運算符添加多個函數。當然也可以通過-=運算符將原本添加的函數刪除掉。
為了演示這個功能,將上述代碼稍作更改。
int add(int a, int b){
Console.WriteLine($"{a}+{b}={a+b}");
return a + b;
}
int minus(int a, int b){
Console.WriteLine($"{a}-{b}={a-b}");
return a-b;
}
void calc(Op func, int a, int b)
{
func(a,b);
}
Op opTest = add;
opTest += minus;
opTest += add;
opTest += minus;
calc(opTest, 3, 4);
Console.WriteLine("減去一個minus");
opTest -= minus;
calc(opTest, 3, 4);
delegate int Op(int a, int b);
其中Op opTest=add的寫法等價于Op opTest = new OpTest(add),但若省略new,則不可寫為var opTest = add,這個時候沒法進行類型推斷。
輸出結果為
3+4=7
3-4=-1
3+4=7
3-4=-1
減去一個minus
3+4=7
3-4=-1
3+4=7
由此可知,委托在調用的時候,會按照+=的先后順序調用函數,并將最后一個調用的函數作為返回值。
而函數在委托中以棧的方式存放,-=會先減去后存入委托中的函數。
拖動按鈕
多播委托在GUI編程中最為常用,尤其是拖動控件時。拖動控件的流程包括三個步驟
- 鼠標點擊控件
- 鼠標拖動控件
- 鼠標松開控件
則對于一個控件來說,其綁定的事件會隨著鼠標的點擊情況而發(fā)生變化
0. 鼠標未點擊時,控件需要響應鼠標點擊事件
- 鼠標點擊之后,控件需要響應鼠標拖動、鼠標松開的事件
- 鼠標拖動時,控件響應的事件并不發(fā)生變化
- 鼠標松開后,控件需要解綁拖動以及松開事件
接下來,實操一下,簡單起見,GUI采用winForm,在新建項目之后,拖動一個按鈕到窗口上,右鍵按鈕->屬性,可以更改一下名字和內容,然后點擊右下角屬性
欄的小閃電,然后注冊MouseDown事件,輸入btnTest_MouseDown并按下回車之后,IDE會自動來到代碼界面,并出現一個空的委托函數。
private void btnTest_MouseDown(object sender, MouseEventArgs e)
{
}
為了理解這個東西的作用,可以在解決方案資源管理器中找到Form1.Designer.cs文件,點進去之后可以看到下面這行代碼
this.btnTest.MouseDown += new System.Windows.Forms.MouseEventHandler(this.btnTest_MouseDown);
換言之,btnTest.MouseDown就是一個多播委托,剛剛我們的行為,為其注冊了一個名為btnTest_MouseDown的實現,盡管這個實現現在還是空的。
若想拖動一個控件,第一步就是按下鼠標,按下鼠標之后,需要再注冊兩個委托,分別再拖動鼠標和松開鼠標時起作用;而松開鼠標和按下鼠標的作用剛好相反,要求取消注冊拖動事件,所以下面分別實現這三個功能。
private void btnTest_MouseDown(object sender, MouseEventArgs e)
{
btnTest.MouseMove += btnTest_MouseMove;
btnTest.MouseLeave += btnTest_MouseLeave;
}
private void btnTest_MouseLeave(object sender, EventArgs e)
{
btnTest.MouseMove -= btnTest_MouseMove;
btnTest.MouseLeave -= btnTest_MouseLeave;
}
private void btnTest_MouseMove(object sender, MouseEventArgs e)
{
int dh = btnTest.Height / 2;
int dw = btnTest.Width / 2;
btnTest.Top = MousePosition.Y - this.Top - dh;
btnTest.Left = MousePosition.X - this.Left - dw;
}
上面需要注意一點,MouseLeave和MouseMove, MoseDown是不同類型的委托,故而創(chuàng)建函數的參數類型是不同的。
btnTest.Top為按鈕頂端距離窗口頂端的距離;MousePosition.Y表示鼠標距離屏幕頂端的距離;this.Top表示窗口頂端距離屏幕頂端的位置,最后再減去一個按鈕高度的一半,相當于是把按鈕的中心移動到鼠標光標處。這種邏輯過于簡單粗暴,實際工作時不會用到,之所以這么寫是因為簡單。
效果如下
原文鏈接:https://tinycool.blog.csdn.net/article/details/128832455
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-09-17 Pandas數據類型轉換df.astype()及數據類型查看df.dtypes的使用_python
- 2023-10-17 git更換遠端地址
- 2022-07-08 C語言算法學習之雙向鏈表詳解_C 語言
- 2023-03-01 shell輸出重定向的實現_linux shell
- 2022-08-22 GoFrame實現順序性校驗示例詳解_Golang
- 2022-09-07 pytest配置文件pytest.ini的具體使用_python
- 2022-11-29 redis配置文件詳解
- 2022-04-22 wampserver You don‘t have permission to access / o
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支