上一篇文章寫了委托的最基本的一些東西,本篇咱們扯扯委托其他的東西。 示例1插件編程 根據對委托的理解,委托可以把一個方法當作參數進行傳遞,利用這個特性我們可以使用委托,實現插件編程。 這裡的Transform方法就是插件方法,它接受一個委托參數。 示例2多播委托 所有的委托都有多播的能力。這就意味著 ...
上一篇文章寫了委托的最基本的一些東西,本篇咱們扯扯委托其他的東西。
示例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核心技術指南