1. 程式人生 > >C#基礎系列——委託實現簡單設計模式

C#基礎系列——委託實現簡單設計模式

前言:上一篇介紹了下多執行緒的相關知識:C#基礎系列——多執行緒的常見用法詳解,裡面就提到了委託變數。這篇簡單介紹下委託的使用。當然啦,園子裡面很多介紹委託的文章都會說道:委託和事件的概念就像一道坎,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和事件就覺得心裡發慌。確實這東西就像最開始學C語言的指標一樣,令人有一種很糾結的感覺,總覺得要呼叫一個方法直接呼叫就行了,為啥非要定義一個委託時執行這個方法呢。其實在C#裡面很多的技術都是為了重用和簡化程式碼而生,委託也不例外,很多使用C#多型去實現的設計模式其實都可以使用委託的方式去改寫,可以理解為一種輕量級的設計模式吧。博主打算抽一篇專門分享下多型和委託實現設計模式的異同。這篇就先介紹簡單委託的使用。

一、什麼是委託:C# 中的委託(Delegate)類似於 C 或 C++ 中函式的指標。用博主的話說,委託就是一種允許將方法名稱作為引數傳遞的引用型別。它定義的是方法的型別,可以說就是方法的抽象,那麼反過來說,方法可以理解為委託的例項,如public delegate void TestDelegate(string str);這種委託定義的就是所有引數型別為string,沒有返回值的方法的一種抽象。

二、為什麼要使用委託:記得博主剛開始做專案的時候看到委託的寫法就頭大,總覺得這是沒事找事,唯一的好處貌似就是程式碼看上去很酷~~隨著工作的累積,發現專案中某些小的需求使用這種輕量級的委託來實現的時候確實能減少很多程式碼量。

三、委託的使用:

1、.Net Framework 裡面的委託型別:使用過委託的朋友可能注意到了C#裡面定義了兩種型別的委託變數,基本能滿足我們的一般需求。

(1)Action型別的委託:C#裡面定義Action委託用於抽象化那種沒有返回值的方法。將Action變數轉到定義可知它的最簡單形式:

    // 摘要: 
    //     封裝一個方法,該方法不具有引數並且不返回值。
    [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089
")] public delegate void Action();

它定義是就是一種沒有返回值沒有引數的委託。同時Action還提供了16個泛型的委託,用於定義方法的傳入引數:

我們來看他們的使用方法,我們首先定義測試的方法:

        private static void Test5(int a, int b, int c)
        { 
            //......
        }


        //無引數無返回值
        private static void Test1()
        {
            Console.WriteLine("Func Test1, No Parameter");
        }

        //有引數無返回值
        private static void Test2(string str)
        {
            Console.WriteLine("Func Test2, Parameter is" + str);
        }

        //無引數有返回值
        private static object Test3()
        {
            Console.WriteLine("Func Test3, Parameter");
            return Guid.NewGuid().ToString();
        }

        //有引數有返回值
        private static object Test4(string strRes)
        {
            Console.WriteLine("Func Test4,  Parameter and Return Value");
            return strRes;
        }

呼叫:

        static void Main(string[] args)
        {
            //1.無參無返回值方法
            var oAction1 = new Action(Test1);
            oAction1.Invoke();//呼叫方式一
            oAction1();//呼叫方式二

            //2.有參無返回值
            var oAction2 = new Action<int, int, int>(Test5);
            oAction2.Invoke(1, 2, 3);
            oAction2(1, 2, 3);
            //匿名方法的呼叫
            var oAction3 = new Action<int, int, int>((a,b,c) => { 
                //......
            });
            oAction3.Invoke(1, 2, 3);
       }

(2)Func型別的委託:還記得Linq裡面的擴充套件方法Where()、Select()等方法的引數嗎。public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)。這裡的引數就是一個Func型別的委託。C#裡面Func型別的委託用於處理有引數有返回值的方法。不多說,上程式碼:

     static void Main(string[] args)
     {
            var oFunc1 = new Func<object>(Test3);
            var ofuncRes1 = oFunc1.Invoke();
            var oFunc2 = new Func<string, object>(Test4);
            oFunc2("a");    
     }

知道了Func的方法就可以推想到我們神奇的lamada表示式了,其實lamada表示式就是一個匿名的委託。

var lstTest = new List<string>();
var lstRes = lstTest.Where(x => x.Contains("_"));

這個Where裡面的lamada表示式我們把他拆解:

private static bool TestWhere(string x)
{
     return x.Contains("_");
}
var oFunc = new Func<string, bool>(TestWhere);
lstRes = lstTest.Where(oFunc);

是不是一樣一樣的~~ 

2、自定義委託:

public delegate void TestDelegate(string str);

其實很多人應該都自己寫過Action、Func型別的委託。其實自己定義一個泛型委託也很簡單:

public delegate void MyAction<in T>();
public delegate TResult MyFunc<in T, out TResult>(T arg);

其實使用起來和系統的Action和Func基本沒有區別。

3、委託的合併和拆解就放在事件裡面分享了。這篇且過之。。。

4、如果按照上面的方法去使用委託,那真的是要彆扭死人了,因為呼叫方法直接用方法名呼叫就好了,何必還要定義一個委託變數去呼叫,這不是將簡單問題複雜化麼。確實,上面只是為了介紹委託而寫的程式碼,實際專案中肯定不會這麼用。其實委託在專案中一般用在將委託變數作為引數傳遞或者函式回撥。來看下面程式碼:

   class Program
    {
        static void Main(string[] args)
        {
            
            Person strHelper = new Person();
            string r1 = strHelper.ProcessFunc("中國人", "你好", new MyDelegate(strHelper.ChineseSayHello));
            string r2 = strHelper.ProcessFunc("English", "Hello", new MyDelegate(strHelper.EnglishSayHello));
            string r3 = strHelper.ProcessFunc("Japanese", "こんにちは", new MyDelegate(strHelper.JapaneseSayHello));

            Console.WriteLine(r1);
            Console.WriteLine(r2);
            Console.WriteLine(r3);

            Console.ReadKey();
        }

    }

    public delegate string MyDelegate(string s1, string s2);
    public class Person
    {
        public string ProcessFunc(string s1, string s2, MyDelegate process)
        {
            return process(s1, s2);
        }

        public string ChineseSayHello(string s1, string s2)
        {
            return s1 +","+ s2;
        }

        public string EnglishSayHello(string s1, string s2)
        {
            return s1 + "," + s2;
        }

        public string JapaneseSayHello(string s1, string s2)
        {
            return s1 +","+ s2;
        }
    }

得到結果:

public string ProcessFunc(string s1, string s2, MyDelegate process)裡面定義了一個回撥函式,可以將任意一個符合這個委託的方法傳遞進去,得到想對應的結果。細看這種設計是不是和工廠設計模式十分相似,我簡單構造了個工廠:

public class Person
    {
        public virtual string SayHello(string s2)
        {
            return s2;
        }
    }
public class Chinese : Person
    {
        public override string SayHello(string s2)
        {
            return "中國人," + s2;
        }
    }

    public class English : Person
    {
        public override string SayHello(string s2)
        {
            return "English," + s2;
        }
    }

    public class Japanese : Person
    {
        public override string SayHello(string s2)
        {
            return "Japanese," + s2;
        }
    }


//Main函式裡面呼叫
class Program
    {
        static void Main(string[] args)
        {
            var r1 = GetPerson("你好").SayHello("你好");
            var r2 = GetPerson("Hello").SayHello("Hello");
            var r3 = GetPerson("こんにちは").SayHello("こんにちは");
            Console.WriteLine(r1);
            Console.WriteLine(r2);
            Console.WriteLine(r3);

            Console.ReadKey();
        }

        public static Person GetPerson(string strType)
        {
            if (strType == "你好")
                return new Chinese();
            else if (strType == "Hello")
                return new English();
            else
                return new Japanese();
        }
        
    }

得到結果和上面相同:

這樣一比較是不是對委託的用法有點感覺了呢~~如果你不怕麻煩,可以在專案是用起來試試,相信你會有收穫~~

示例下載

相關推薦

C#基礎系列——委託實現簡單設計模式

前言:上一篇介紹了下多執行緒的相關知識:C#基礎系列——多執行緒的常見用法詳解,裡面就提到了委託變數。這篇簡單介紹下委託的使用。當然啦,園子裡面很多介紹委託的文章都會說道:委託和事件的概念就像一道坎,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和事件就覺得心裡發慌。確實這東西就像最開始學C語言

C#基礎系列委託實現簡單設計模式(1)

前言:這篇簡單介紹下委託的使用。當然啦,園子裡面很多介紹委託的文章都會說道:委託和事件的概念就像一道坎,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和事件就覺得心裡發慌。確實這東西就像最開始學C語言的指標一樣,令人有一種很糾結的感覺,總覺得要呼叫一個

C#基礎系列——委託設計模式(二)

前言:前篇 C#基礎系列——委託實現簡單設計模式 簡單介紹了下委託的定義及簡單用法。這篇打算從設計模式的角度去解析下委託的使用。我們知道使用委託可以實現物件行為(方法)的動態繫結,從而提高設計的靈活性。上次說過,方法可以理解為委託的例項,站在方法的層面,委託例項的一個非常有用的特性是它既不知道,也不關心其封裝

C#基礎委託簡單使用

        委託是一個類,它定義了方法的型別,使得可以將方法當作另一個方法的引數來進行傳遞,這種將方法動態地賦給引數的做法,可以避免在程式中大量使用If-Else(Switch)語句,同時使得程式具有更好的可擴充套件性。         委託的關鍵字delegate;示

C#基礎系列委託設計模式(2)

前言:這篇打算從設計模式的角度去解析下委託的使用。我們知道使用委託可以實現物件行為(方法)的動態繫結,從而提高設計的靈活性。上次說過,方法可以理解為委託的例項,站在方法的層面,委託例項的一個非常有用的特性是它既不知道,也不關心其封裝方法所屬類的詳細資訊,對它來說最重

啃食c++(簡單設計模式)

簡單工廠模式 該設計模式是多型的一種應用例項,簡單工廠模式是有一個生產物件決定生產那一產品,例如接下來的例子中,將friut作為父類,其子類就是各種水果,在這裡就建立了兩個子類引入,然後將各種水果物件作為生產者garden的私有資料成員,通過出生產者來獲取想要的水果型別。 #includ

C++實現Builder設計模式

------------------------------ 以下為.h檔案 -------------------------------------------- #pragma once #include <iostream> using namespace std; class S

C++筆記(五) UML/設計模式簡單工廠模式及工廠模式

一、UML(統一建模語言) 模型:對問題的書面上的無歧義文字或圖形的描述,簡言之,模型是對現實的簡化。 建模:對現實系統進行適當的過濾,用適當的表現規則描述出簡介的模型問題。 UML:是一種基於面向物件的視覺化建模語言。UML採用了一組形象畫的額圖形符號作為建模語言,使

設計模式系列之一:簡單工廠模式

前言 設計模式能夠幫助我們設計出健壯,低耦合性的程式碼,從此和高耦合的程式碼say goodbye!在所有的的設計模式中,簡單工廠算是我們平時接觸比較多的吧,多執行緒中的消費者工廠類與生產者工廠類應該算是接觸最早的設計模式,簡單工廠模式要解決的首要問題就是降低

簡單的介面和抽象類實現模板設計模式

一、先使用介面實現模板設計模式 1、先寫模板模式中大家公共的方法,將該方法放到一個接口裡: public interface MyPublic { public void step02(); } 2、寫模板類(step01和step03是公共的不變的方法,ste

C#基礎系列:開發自己的窗體設計器(PropertyGrid顯示中文屬性名)

  既然是一個窗體設計器,那就應該能夠設定控制元件的屬性,設定屬性最好的當然是PropertyGrid了,我們僅僅需要使用一個PropertyGrid.SelectedObject = Control就可以搞定,讓PropertyGrid顯示Control的所有屬性。可是這

C#實現簡單工廠模式

(文章地址:http://mp.weixin.qq.com/s/kkilLvrr7h3qgqiwVtzPfw) 末尾有工程檔案 設計模式雖然對效能來說不會有很大的提升,但是許多設計模式在開發的過程中還是非常有用的,運用好設計模式,可以幫助提升開發效率,加快開發速度 。

「七天自制PHP框架」第三天:PHP實現設計模式

爭論 框架 啟動 興趣 註意 end php imp close 往期回顧:「七天自制PHP框架」第二天:模型與數據庫,點擊此處 原文地址:http://www.cnblogs.com/sweng/p/6624845.html,歡迎關註:編程老頭 為什麽要使用設計模式?

我的設計模式簡單設計模式

單例模式 代理模式 策略模式 門面模式 適配器模式 1.例子模式單例模式 Singleton Patternonly one 原則問題:實例只有一個方案:only(私有化構造) one(提供一個入口) 方案的問題:入口的線程問題 多例模式 Multition Pattern有上限多例

mysql 開發基礎系列15 索引的設計和使用

hash索引 drop myisam mar 至少 不同類 不同 執行 例如 一.概述   所有mysql 列類型都可以被索引,是提高select查詢性能的最佳方法。 根據存儲引擎可以定義每個表的最大索引數和最大索引長度,每種引擎對每個表至少支持16個索引,總索引長度至少為

c#基礎系列3---深入理解ref 和out

ref 聲明 函數的參數 .... -- 新增 tel struct 結果 “大菜”:源於自己剛踏入猿途混沌時起,自我感覺不是一般的菜,因而得名“大菜”,於自身共勉。 擴展閱讀 c#基礎系列1---深入理解 值類型和引用類型 c#基礎系列2---深入理解 Str

直譯器模式( Interpreter Pattern ): 最不容易實現設計模式

參考書籍: 《Design Patterns: Elements of Reusable Object-Oriented Software》 設計模式用前須知 設計模式種一句出現頻率非常高的話是,“ 在不改動。。。。的情況下, 實現。。。。的擴充套

MyEclipse下用struts框架實現MVC設計模式

 MyEclipse下用struts框架實現MVC設計模式 環境配置 Ø JDK 5.0 Ø Eclipse 3.2 Ø MyEclipse 5

Java基礎:23種Java設計模式

設計模式主要分三個型別:建立型、結構型和行為型。 其中建立型有: 一、Singleton,單例模式:保證一個類只有一個例項,並提供一個訪問它的全域性訪問點 二、Abstract Factory,抽象工廠:提供一個建立一系列相關或相互依賴物件的介面,而無須指定它們的具體類。 三、Fac

JAVA基礎(57)---模板設計模式

由抽象類衍生出的一種設計模式:模板設計模式(模板方法設計模式) 模板設計模式,就是將完成某件事固定不變的步驟設計成模板,要用 abstract 修飾的方法,然後將不確定的業務邏輯設計成抽象的方法,目的就是讓子類繼承並且複寫該抽象方法,能夠為了實現可擴充套件性。官方的說法是:定義一個操作中的演