C# 委託學習

示例1插件編程

根據對委託的理解,委託可以把一個方法當作參數進行傳遞,利用這個特性我們可以使用委託,實現插件編程。

public delegate int Transformer(int x);

class Util{
    pubilc static void Transform(int[] values, Transformer t){
        for(int i = 0; i < values.Length; i++){
            values[i] = t?.Invke(values[i]);
        }
    }
}

class Test{
    static void Main(){
        int[] values = {1,2,3};
        Util.Transform(values, Sqare);
        
        foreach(int i in values){
            Console.WriteLine(i + " "); //1 4 9
        }
    }
    
    static int Sqare (int x) => x * x;
}

這裏的Transform方法就是插件方法,它接受一個委託參數。

示例2多播委託

所有的委託都有多播的能力。這就意味着一個委託可以引用一個方法,或者引用一個組方法。委託使用 += 和 -=運算符聯結多個委託實例。

public class People{}
public class Student:People{}
public delegate void Action();

class Program
{
    static void Say(){
        Console.WriteLine("Say HI");
    }
    static void Write(){
        Console.WriteLine("Write Anything");
    }
    
    Action action = Say;
    action += Write;//action = action + Write;
    action();
    
    /*
        Say HI
        Write Anything
    */
    
    
    
}

委託會按照添加的順序依次觸發。如果存在返回值,那麼調用者會將最後一個帶有非void返回值類型的方法返回值進行返回,其他的返回值將會拋棄。

- 和-= 運算符會從左側委託操作數中將右側的委託操作刪除。
對於爲值爲null的委託執行 + 或者+= 操作,等價於爲委託指定一個新的值。同樣在當委託只有一個目標方法時,執行-=操作等價於爲委託指定null值。
由於委託是一個類,所以委託是不可變,每次執行 += 或者-= 實質上等價於從新創建一個新的委託實例,併爲它賦值。
具體使用,比如說我們要建一棟大樓,需要很長一段時間,但是公司有要求每建好一層需要給公司彙報一下。

public delegate void ProgressReporter(int floor);

public class Edifice{
    public static void Build(ProgressReporter p){
        for(int i = 0; i < 18; i++){
            p(i);
            
            System.Threading.Thread.Sleep(1000);//添加點時間
        }
    }
}
class Test{
    static void Main(){
        ProgressReporter p = WriteProgressToConsole;
        p += AdviseToCompany;
        Edifice.Build(p);
    }
    
    static void WriteProgressToConsole(int fool) => Console.WriteLine($"{fool}層已建成");
    
    static void AdviseToCompany(int fool) => Console.WriteLine($"**項目,已經建好{fool}層。");
    
    
}

示例3泛型委託

委託類型可以包含泛型類型參數,如:

public delegate T Transformer<T> (T t);

通過一個泛型參數,我們可以定義一個通用的Transformer,讓它對任何類型都有效:

public class util{
    public static void Transform<T> (T[] values, Transformer<T> t){
        for(int i = 0; i < values.Length; i++){
            values[i] = t(values[i]);
        }
    }
}
class Test{
    static void Main(){
        int[] values = {1,2,3};
        Util.Transformer(values, Square);
        
        foreach(int i in values){
            Console.Write(i + " "); //1 4 9
        }
    }
    
    static int Sqare (int x) => x * x;
    
}

既然委託支持泛型參數,那麼就可以定義一些小型的委託類型,它們可以具有任意的返回類型和合理的數目的參數,類如系統定義好的Action委託和Func委託(out和in標記可變性修飾符,在逆變和協變中有解釋)。

delegate void Action();
delegate void Action<in T> (T arg);
delegate void Action<in T1, in T2> (T1 arg1, T2 arg2)
………
delegate TResule Func(out TResule)();
delegate TResule Func<in T, out TResule> (T arg);
delegate TResule Func<in T1, in T2, out TResule> (T1 arg1, T2 arg2)
………

其中Action和Func 都可以支持16個參數。
上面的Transform重寫.

public static void Transform<T> (T[] values, Func<T, T> transformer){
    for(int i = 0; i < values.Length; i++){
        values[i] = transformer(values[i]);
    }
}

參考自C#7.0核心技術指南
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章