成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

C#委托基礎(chǔ):談委托和接口

開發(fā) 后端
C#委托是.NET Framework中一個(gè)非常炫的特性,我們幾乎每天都會(huì)接觸委托,使用委托。本文介紹了有關(guān)C#委托的一些基礎(chǔ)。

本文是博客園中近日關(guān)于C#委托的討論所衍生出來的一個(gè)系列中的***篇,文章作者麒麟.NET對(duì)C#委托的內(nèi)涵和外延進(jìn)行了討論。用麒麟.NET的話來說:“委托是.NET Framework中一個(gè)非常炫的特性,絕不會(huì)向有些評(píng)論里說的那樣,根本沒有機(jī)會(huì)接觸。恰恰相反,我們幾乎每天都會(huì)接觸委托,使用委托?!?/P>

那么,先從示例開始,了解什么是C#委托吧。

從示例開始

假設(shè)一個(gè)系統(tǒng)的用戶登錄模塊有如下所示的代碼

  1. class User  
  2. {  
  3.     public string Name { getset; }  
  4.  
  5.     public string Password { getset; }  
  6. }  
  7.  
  8. class UserService  
  9. {  
  10.     public void Register(User user)  
  11.     {   
  12.         if (user.Name == "Kirin")  
  13.         {  
  14.             Log("注冊(cè)失敗,已經(jīng)包含名為" + user.Name + "的用戶");  
  15.         }  
  16.         else 
  17.         {  
  18.             Log("注冊(cè)成功!");  
  19.         }  
  20.     }  
  21.  
  22.     privte void Log(string message)  
  23.     {  
  24.         Console.WriteLine(message);  
  25.     }  
  26. }  

UserService類封裝用戶登錄的邏輯,并根據(jù)不同的登錄情況向控制臺(tái)打印不同的日志內(nèi)容。當(dāng)程序關(guān)閉時(shí),所記錄的日志自然也隨之消失。

客戶端的代碼為

  1. class Program  
  2. {  
  3.     static void Main(string[] args)  
  4.     {  
  5.         User user = new User { Name = "Kirin", Password = "123" };  
  6.         UserService service = new UserService();  
  7.         service.Register(user);  
  8.         Console.ReadLine();  
  9.     }  

使用策略模式

然而這樣的設(shè)計(jì)肯定是無(wú)法滿足用戶的需求的,用戶肯定希望能夠查看以前的日志記錄,而不僅僅是程序打開以后的內(nèi)容。如果我們僅僅修改Log方法的實(shí)現(xiàn),那么用戶需求再次改變時(shí)我們?cè)撊绾翁幚砟??難道要無(wú)休止地修改Log方法嗎?

既然日志記錄的方式是變化的根源,我們自然會(huì)想到將其進(jìn)行封裝。我們創(chuàng)建一個(gè)名為ILog的接口。

  1. interface ILog  
  2. {  
  3.     void Log(string message);  
  4. }  

并創(chuàng)建兩個(gè)實(shí)現(xiàn)了ILog的類,ConsoleLog和TextLog,分別用來向控制臺(tái)和文本文件輸出日志內(nèi)容。

  1. class ConsoleLog : ILog  
  2. {  
  3.     public void Log(string message)  
  4.     {  
  5.         Console.WriteLine(message);  
  6.     }  
  7. }  
  8.    
  9. class TextLog : ILog  
  10. {  
  11.     public void Log(string message)  
  12.     {  
  13.         using (StreamWriter sw = File.AppendText("log.txt"))  
  14.         {  
  15.             sw.WriteLine(message);  
  16.             sw.Flush();  
  17.             sw.Close();  
  18.         }  
  19.     }  
  20. }  

在UserService類中添加一個(gè)ILog類型的屬性LogStrategy。

  1. class UserService  
  2. {  
  3.     public ILog LogStrategy { getset; }  
  4.  
  5.     public UserService()  
  6.     {  
  7.         LogStrategy = new ConsoleLog();  
  8.     }  
  9.  
  10.     public void Register(User user)  
  11.     {   
  12.         if (user.Name == "Kirin")  
  13.         {  
  14.             LogStrategy.Log("注冊(cè)失敗,已經(jīng)包含名為" + user.Name + "的用戶");  
  15.         }  
  16.         else 
  17.         {  
  18.             LogStrategy.Log("注冊(cè)成功!");  
  19.         }  
  20.     }  
  21. }  
  22.  

客戶端代碼變?yōu)槿缦滦问健?/P>

  1. class Program  
  2. {  
  3.     static void Main(string[] args)  
  4.     {  
  5.         User user = new User { Name = "Kirin", Password = "123" };  
  6.         UserService service = new UserService { LogStrategy = new TextLog() };  
  7.         service.Register(user);  
  8.         Console.ReadLine();  
  9.     }  

在聲明UserService的時(shí)候,還可以將將LogStrategy設(shè)置為TextLog。這樣在UserService進(jìn)行邏輯處理時(shí),使用的LogStrategy即為TextLog,日志將輸出到文本文件中。

我們?cè)诟墒裁??我們?cè)谥貥?gòu)。重構(gòu)的結(jié)果是什么?重構(gòu)的結(jié)果是實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的策略模式。

使用委托

然而策略模式仍然不能滿足客戶的需求,這是為什么呢?

1. 用戶也許會(huì)希望自定義Log的實(shí)現(xiàn)。當(dāng)然,你可以通過在客戶代碼處擴(kuò)展ILog來實(shí)現(xiàn)自己的日志記錄方式。如

  1. class TextBoxLog : ILog  
  2. {  
  3.     private TextBox textBox;  
  4.  
  5.     public TextBoxLog(TextBox textBox)  
  6.     {  
  7.         this.textBox = textBox;  
  8.         this.textBox.Multiline = true;  
  9.     }  
  10.  
  11.     public void Log(string message)  
  12.     {  
  13.         textBox.AppendText(message);  
  14.         textBox.AppendText(Environment.NewLine);  
  15.     }  
  16. }  
  17.  

但這種方案是否過于復(fù)雜呢?如果用戶希望在ListView或其他控件上顯示,是否需要逐個(gè)創(chuàng)建新類呢?并且這樣的實(shí)現(xiàn)是否與客戶端的耦合過于緊密呢?比如用戶希望在ListView的各個(gè)列中顯示日志內(nèi)容、時(shí)間、來源等不同內(nèi)容,那么在ListViewLog中對(duì)ListView硬編碼是否很難重用呢?

2. 用戶也許會(huì)希望同時(shí)使用多種日志記錄方式。比如,同時(shí)向控制臺(tái)、文本文件、客戶端控件和事件查看器中輸出日志。你當(dāng)然可以在UserService中維護(hù)一個(gè)List<ILog>,但這時(shí)UserService的職責(zé)過多,顯然違反了SRP。

下面介紹本文的主角:委托。

我們首先來創(chuàng)建一個(gè)名為L(zhǎng)og的委托,它接收一個(gè)string類型的參數(shù)。

  1. public delegate void Log(string message); 

然后在UserService類中添加一個(gè)Log委托類型的屬性LogDelegate。

  1. class UserService  
  2. {  
  3.     public Log LogDelegate { getset; }  
  4.  
  5.  
  6.     // …  
  7. }  

在客戶端,我們直接聲明兩個(gè)靜態(tài)方法,它們都包含一個(gè)string類型的參數(shù),并且沒有返回值。

  1. static void LogToConsole(string message)  
  2. {  
  3.     Console.WriteLine(message);  
  4. }  
  5.  
  6. static void LogToTextFile(string message)  
  7. {   
  8.     using (StreamWriter sw = File.AppendText("log.txt"))  
  9.     {  
  10.         sw.WriteLine(message);  
  11.         sw.Flush();  
  12.         sw.Close();  
  13.     }  
  14. }  

客戶端聲明UserService的代碼變?yōu)?/P>

  1. static void Main(string[] args)  
  2. {  
  3.     User user = new User { Name = "Kirin", Password = "123" };  
  4.     UserService service = new UserService();  
  5.     service.LogDelegate = LogToConsole;  
  6.     service.LogDelegate += LogToTextFile;  
  7.     service.Register(user);  
  8.      
  9.     Console.ReadLine();  

在構(gòu)造委托時(shí),我們還可以使用匿名方法和Lambda表達(dá)式,在老趙的文章中詳細(xì)闡述了這些寫法的演變。

對(duì)于何時(shí)使用委托,何時(shí)使用接口(即策略模式),MSDN中有明確的描述:

在以下情況下,請(qǐng)使用委托:

◆當(dāng)使用事件設(shè)計(jì)模式時(shí)。

◆當(dāng)封裝靜態(tài)方法可取時(shí)。

◆當(dāng)調(diào)用方不需要訪問實(shí)現(xiàn)該方法的對(duì)象中的其他屬性、方法或接口時(shí)。

◆需要方便的組合。

◆當(dāng)類可能需要該方法的多個(gè)實(shí)現(xiàn)時(shí)。

在以下情況下,請(qǐng)使用接口:

◆當(dāng)存在一組可能被調(diào)用的相關(guān)方法時(shí)。

◆當(dāng)類只需要方法的單個(gè)實(shí)現(xiàn)時(shí)。

◆當(dāng)使用接口的類想要將該接口強(qiáng)制轉(zhuǎn)換為其他接口或類類型時(shí)。

◆當(dāng)正在實(shí)現(xiàn)的方法鏈接到類的類型或標(biāo)識(shí)時(shí):例如比較方法。

您可能覺得上面的例子闡述委托和接口有些過于牽強(qiáng),事實(shí)上有些時(shí)候的確很難選擇使用接口還是委托。Java中沒有委托,但所有委托適用的情況同樣可以使用包含單一方法的接口來實(shí)現(xiàn)的。在某種程度上,可以說委托是接口(僅定義了單一方法)的一種輕量級(jí)實(shí)現(xiàn),它更靈活,也更方便。

以上就是對(duì)于C#委托中一些基本概念的介紹。

【編輯推薦】

  1. C#委托實(shí)例簡(jiǎn)單分析
  2. 一個(gè).NET委托的故事:彼得,老板和宇宙
  3. 解惑答疑:C#委托和事件
  4. 各版本.NET委托的寫法回顧
  5. 換一個(gè)角度看.NET中的理解委托和事件
責(zé)任編輯:yangsai 來源: 博客園
相關(guān)推薦

2011-04-22 09:14:26

C#委托

2010-12-22 10:21:17

C#基礎(chǔ)

2009-08-18 10:35:26

C#委托

2009-08-27 16:53:01

C#委托C#事件

2009-08-20 18:37:52

委托C#異步委托

2009-08-20 18:11:08

C#異步委托

2009-08-18 10:54:17

C#事件和委托

2009-10-09 09:07:40

C#委托和事件

2009-08-26 14:27:54

C#委托和事件

2024-10-05 00:00:35

Action?C#Func?

2024-05-30 12:24:03

C#開發(fā)

2009-09-01 18:36:35

C#委托實(shí)例

2024-12-23 08:00:00

委托C#編程

2024-09-29 09:28:38

Action?C#

2024-05-16 13:36:04

C#委托事件

2010-09-14 14:05:42

C#委托

2011-05-20 17:50:45

C#

2024-05-16 12:33:37

C#編程指針

2023-09-26 07:38:53

c#Lambda表達(dá)式

2009-08-24 15:50:23

C# 泛型C# 泛型委托
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 亚洲精品成人av久久 | 国产精品一级 | 一级欧美| 亚洲www| 日韩欧美在线视频播放 | 成人精品一区亚洲午夜久久久 | 免费电影av | 99热国产免费 | 精品国产乱码久久久久久闺蜜 | 亚洲视频免费在线观看 | 亚洲精品自在在线观看 | 在线视频91 | av片毛片| 日韩成人影院在线观看 | 亚洲成网站 | 成人欧美一区二区三区黑人孕妇 | 国产有码 | 欧美日韩国产一区二区三区 | 日韩av高清在线 | 九色www| 欧美一区在线看 | 激情六月丁香婷婷 | 成人性视频在线 | 亚洲精品黄色 | 九一视频在线播放 | 91麻豆精品一区二区三区 | 91精品国产综合久久久久蜜臀 | 美女一级毛片 | 日本天堂视频在线观看 | 亚洲国产免费 | 日韩中文在线 | 国产中文视频 | 国产精品精品 | 成人在线观看黄 | 影音先锋中文字幕在线观看 | 久久综合久久综合久久 | 一区二区三区视频在线观看 | 日韩精品成人一区二区三区视频 | 国产精品五月天 | 国产精品亚洲片在线播放 | 日日日视频 |