c#學習筆記之委託

委託

最近本身在調試C#項目,發現常常能夠看到委託和lambda表達式,各類花裏胡哨的寫法把我給整的雲裏霧裏的,因而本身特地花了一點功夫來整理關於delegate的相關知識,方便本身往後查閱。數組

何爲委託

委託是.NET中的尋址方法,和C++的函數指針很像;可是委託是類型安全的類,定義了返回類型和參數類型,也就是說委託一種用戶自定義的類型,和普通的類同樣;安全

委託的使用

聲明委託

delegate void IntMethodInvoker(int x);    //定義委託IntMethodInvoker, 參數是int,返回類型void

咱們能夠把委託當作是一件事情,就是給方法名字和返回類型指定一個別名函數

從上面的例子能夠總結出聲明委託的模板以下:spa

  • delegate + 返回類型 + 委託類型名 + 參數列表

委託的使用

實例化委託,而且須要對其進行初始化,這樣能夠相似地當作一個變量使用了,下面給出一個具體的例子來講明如何使用委託。指針

using System;
    
    namespace DelegateSamples{
    
        delegate double DoubleOp(double x);    // 聲明一個委託類型
        class MathOperations
        {
            public static doube MultiplyByTwo(double value)
                return value * 2;
    
            public static double Square(double value)
                return value * value;
        }
        
        class Program
        {
            static void Main()
            {
                // 聲明一個委託數組,就像普通數組同樣
                DoubleOp[] operations = {MathOperations.MultiplyByTwo, MathOperations.Square};
                
                for(int i = 0; i < operations.length; i++)
                {
                    Console.WriteLine("using operations[{0}]:", i);
                    ProcessAndDisplayNumber(operations[i], 3.2);
                    Console.WriteLine();
                }
            }
        
            static void ProcessAndDisplayNumber(DoubleOp action, double value)
            {
                double res = action(value);         // 調用action實際封裝的方法
                Console.WrireLine("Value is {0}, result of operation is {1}", value, res);
            }
         }

在調用委託的時候,最後判斷委託是否爲null,否則可能會引發異常調試

Action 和Func 委託

Action<T>委託表示引用一個void返回類型的方法,Action<T>有不少種變體,Action<in T>調用帶一個參數的方法,沒有泛型參數的Action類調用不帶參數的方法;
Func<T>委託相似,表示引用帶返回類型的方法,Func<T>也有不少變體,Func<Out TResult>表示調用帶返回類型但沒有參數的方法,Func<in T, out TRsult>調用一個帶參數的方法,以此類推;code

// 聲明一個返回double類型,而且帶一個double參數的委託
Func <double, double> operations = {MathOperations.MultiplyByTwo, MathOperations.Square};

// 注意這個方法和上面方法的不同,利用了Func類
static void ProcessAndDisplayNumber(Func <double, double> action, double value)
{
        double res = action(value);         // 調用action實際封裝的方法
        Console.WrireLine("Value is {0}, result of operation is {1}", value, res);
}

多播委託

在以前的例子中,每一個委託都只含有一個方法調用,也就是說調用多少次委託就是調用多少次方法。orm

可是,一個委託也能夠包含多個方法,這種委託叫作多播委託,所以,這種委託必須返回void,否則返回的數據是不對的ip

Action<double> operations = MathOperations.MultiplyByTwo;
    operations += MathOperations.Square;    //這裏在給委託添加一個方法

對於多播委託的使用,調用方法鏈的順序並沒獲得正式定義,這要求咱們儘可能避免依賴特定順序調用方法的代碼;編譯器

從上面的例子能夠知道,多播委託是能夠識別+,+=,-,-=這些符號的,下面給出具體的示意:

  • +=: 表示委託新增一個方法
  • -=: 表示委託減小一個方法

匿名方法

在上面的例子中,委託所調用的方法,都是咱們本身預先寫好的,可是委託也可使用匿名方法,也就是將匿名方法用做委託的參數,這在實例化委託的會有一些不同的,具體以下面例子所示:

string name = "";
    
    // Func<string, string>委託接受一個string參數,返回一個string,注意匿名方法的實現,delegate開頭
    Func<string, string> anonDel = delegate(string param){
        param += name;
        param += "just for test";
        return param;
    };

使用匿名方法須要遵照的規則:

  1. 在匿名方法中不能使用跳轉語句(goto、break、continue),匿名方法外部的語句也不能跳轉到匿名方法內部;
  2. 在匿名方法中不能訪問不徹底的代碼,也不能訪問在匿名方法外部定義的ref、out參數;

在C#3.0以後,lambda表達式代替了匿名方法,寫起來感受更舒服;

Lambda表達式

lambda表達式主要是用來替代匿名方法的,由於顯然委託知道他本身須要調用的是什麼方法,不須要聲明delegate關鍵字,在參數和方法體之間插入=>,表示「goes to",具體示例以下所示:

string name = "";
    
    // Func<string, string>委託接受一個string參數,返回一個string,這裏使用lambda表達式
    Func<string, string> anonDel = param => {
        param += name;
        param += "just for test";
        return param;
    };
   // 這樣的lambda表達式是否是很優雅,就是調試程序的時候會有點煩

爲了更好地使用lambda表達式,方便咱們本身寫代碼寫的花裏花哨的,就對其多作一點介紹:

參數

  1. 若是隻有一個參數,就只須要寫出參數名字就行

    Func<string, string> oneParam = s => String.Format("change to Upper {0}", s.ToUpper());
  2. 使用多個參數,就把參數用寫在()裏

    Func<double, double, double> twoParams= (x, y) => x * y;    // 返回x*y

在使用多個參數的時候,我以爲仍是在參數前面加上類型比較好,便於理解,例如(double x, double y) => x * y;

多行代碼

  1. 只有一條語句,方法裏面不須要{}和return,編譯器會自動添加一個隱式的return

    Func<double, double, double> result = x, y => x * y;
  2. 含有多條語句,須要加上{}和return

    string lastname = "Alex";
    Func<string ,string> printName = name =>
        {
            name += lastname;
            return String.Format("Being Upper: {0}",name);
        }
相關文章
相關標籤/搜索