91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

C#委托是什么

發布時間:2021-12-03 10:18:03 來源:億速云 閱讀:148 作者:iii 欄目:編程語言

這篇文章主要介紹“C#委托是什么”,在日常操作中,相信很多人在C#委托是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C#委托是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

從示例開始

假設一個系統的用戶登錄模塊有如下所示的代碼

class User  {      public string Name { get; set; }       public string Password { get; set; }  }   class UserService  {      public void Register(User user)      {           if (user.Name == "Kirin")          {              Log("注冊失敗,已經包含名為" + user.Name + "的用戶");          }          else         {              Log("注冊成功!");          }      }       privte void Log(string message)      {          Console.WriteLine(message);      }  }

UserService類封裝用戶登錄的邏輯,并根據不同的登錄情況向控制臺打印不同的日志內容。當程序關閉時,所記錄的日志自然也隨之消失。

客戶端的代碼為

class Program  {      static void Main(string[] args)      {          User user = new User { Name = "Kirin", Password = "123" };          UserService service = new UserService();          service.Register(user);          Console.ReadLine();      }  }

使用策略模式

然而這樣的設計肯定是無法滿足用戶的需求的,用戶肯定希望能夠查看以前的日志記錄,而不僅僅是程序打開以后的內容。如果我們僅僅修改Log方法的實現,那么用戶需求再次改變時我們該如何處理呢?難道要無休止地修改Log方法嗎?

既然日志記錄的方式是變化的根源,我們自然會想到將其進行封裝。我們創建一個名為ILog的接口。

interface ILog  {      void Log(string message);  }

并創建兩個實現了ILog的類,ConsoleLog和TextLog,分別用來向控制臺和文本文件輸出日志內容。

class ConsoleLog : ILog  {      public void Log(string message)      {          Console.WriteLine(message);      }  }     class TextLog : ILog  {      public void Log(string message)      {          using (StreamWriter sw = File.AppendText("log.txt"))          {              sw.WriteLine(message);              sw.Flush();              sw.Close();          }      }  }

在UserService類中添加一個ILog類型的屬性LogStrategy。

class UserService  {      public ILog LogStrategy { get; set; }       public UserService()      {          LogStrategy = new ConsoleLog();      }       public void Register(User user)      {           if (user.Name == "Kirin")          {              LogStrategy.Log("注冊失敗,已經包含名為" + user.Name + "的用戶");          }          else         {              LogStrategy.Log("注冊成功!");          }      }  }

客戶端代碼變為如下形式。

class Program  {      static void Main(string[] args)      {          User user = new User { Name = "Kirin", Password = "123" };          UserService service = new UserService { LogStrategy = new TextLog() };          service.Register(user);          Console.ReadLine();      }  }

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

我們在干什么?我們在重構。重構的結果是什么?重構的結果是實現了一個簡單的策略模式。

使用委托

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

1. 用戶也許會希望自定義Log的實現。當然,你可以通過在客戶代碼處擴展ILog來實現自己的日志記錄方式。如

class TextBoxLog : ILog  {      private TextBox textBox;       public TextBoxLog(TextBox textBox)      {          this.textBox = textBox;          this.textBox.Multiline = true;      }       public void Log(string message)      {          textBox.AppendText(message);          textBox.AppendText(Environment.NewLine);      }  }

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

2. 用戶也許會希望同時使用多種日志記錄方式。比如,同時向控制臺、文本文件、客戶端控件和事件查看器中輸出日志。你當然可以在UserService中維護一個List<ILog>,但這時UserService的職責過多,顯然違反了SRP。

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

我們首先來創建一個名為Log的委托,它接收一個string類型的參數。

public delegate void Log(string message);

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

class UserService  {      public Log LogDelegate { get; set; }        // …  }

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

static void LogToConsole(string message)  {      Console.WriteLine(message);  }   static void LogToTextFile(string message)  {       using (StreamWriter sw = File.AppendText("log.txt"))      {          sw.WriteLine(message);          sw.Flush();          sw.Close();      }  }

客戶端聲明UserService的代碼變為

static void Main(string[] args)  {      User user = new User { Name = "Kirin", Password = "123" };      UserService service = new UserService();      service.LogDelegate = LogToConsole;      service.LogDelegate += LogToTextFile;      service.Register(user);           Console.ReadLine();  }

在構造委托時,我們還可以使用匿名方法和Lambda表達式,在老趙的文章中詳細闡述了這些寫法的演變。

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

在以下情況下,請使用委托:

◆當使用事件設計模式時。

◆當封裝靜態方法可取時。

◆當調用方不需要訪問實現該方法的對象中的其他屬性、方法或接口時。

◆需要方便的組合。

◆當類可能需要該方法的多個實現時。

在以下情況下,請使用接口:

◆當存在一組可能被調用的相關方法時。

◆當類只需要方法的單個實現時。

◆當使用接口的類想要將該接口強制轉換為其他接口或類類型時。

◆當正在實現的方法鏈接到類的類型或標識時:例如比較方法。

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

到此,關于“C#委托是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

嫩江县| 芜湖市| 阿图什市| 梅河口市| 通辽市| 三门县| 滁州市| 泰兴市| 宜川县| 新沂市| 肃北| 拜泉县| 万盛区| 盱眙县| 新津县| 黑龙江省| 濮阳市| 清涧县| 黔西| 瓦房店市| 辽宁省| 福安市| 开封市| 鲁山县| 进贤县| 响水县| 资讯| 建宁县| 长岭县| 天门市| 铜陵市| 绥化市| 乐都县| 韶关市| 丰县| 旬邑县| 清镇市| 郑州市| 凯里市| 洛宁县| 汕尾市|