委托
最简单的委托示例:
1 // 该委托可以指向任何传入两个整数并返回一个整数的方法 2 public delegate int BinaryOp( int x, int y ); 3 public class SimpleMath 4 { 5 public int Add( int x, int y ) 6 { return x + y; } 7 public int Subtract( int x, int y ) 8 { return x - y; } 9 public static int SquareNumber( int a ) 10 { return a * a; } 11 } 12 class Program 13 { 14 static void Main( string[] args ) 15 { 16 Console.WriteLine("***** Simple Delegate Example *****\n"); 17 18 SimpleMath m = new SimpleMath(); 19 20 BinaryOp b = new BinaryOp(m.Add); 21 DisplayDelegateInfo(b); 22 23 Console.WriteLine("10 + 10 is {0}", b(10, 10)); 24 25 Console.ReadLine(); 26 } 27 static void DisplayDelegateInfo( Delegate delObj ) 28 { 29 foreach (Delegate d in delObj.GetInvocationList()) 30 { 31 Console.WriteLine("Method Name: {0}", d.Method); 32 Console.WriteLine("Type Name: {0}", d.Target); 33 } 34 } 35 }
支持多路广播的委托示例:
1 /* 2 * 2015.5 3 * Car.cs 4 */ 5 using System; 6 using System.Collections.Generic; 7 using System.Linq; 8 using System.Text; 9 using System.Threading.Tasks; 10 11 namespace CarDelegate 12 { 13 public class Car 14 { 15 // 内部状态数据 16 public int CurrentSpeed { get; set; } 17 public int MaxSpeed { get; set; } 18 public string PetName { get; set; } 19 private bool carIsDead = false; 20 21 // 构造函数 22 public Car() { MaxSpeed = 180; } 23 public Car( string name, int maxSp, int currSp ) 24 { 25 CurrentSpeed = currSp; 26 MaxSpeed = maxSp; 27 PetName = name; 28 } 29 30 // 定义委托类型 31 public delegate void CarEngineHandler( string msgForCaller ); 32 33 // 定义每个委托类型的成员变量 34 private CarEngineHandler listOfHandlers; 35 36 // 添加注册函数 37 public void RegisterWithCarEngine( CarEngineHandler methodToCall ) 38 { // 给每个委托对象添加多个方法 39 // 支持多路广播,可以使用 +=操作符,或直接调用Delegate.Combine() 40 41 // listOfHandlers += methodToCall; 42 43 if (listOfHandlers == null) 44 listOfHandlers = methodToCall; 45 else 46 Delegate.Combine(listOfHandlers, methodToCall); 47 } 48 49 public void UnRegisterWithCarEngine( CarEngineHandler methodToCall ) 50 { // 从委托的调用列表移除成员, 也可调用 Delegate.Remove() 51 52 listOfHandlers -= methodToCall; 53 } 54 55 public void Accelerate( int delta ) 56 { 57 if (carIsDead) 58 { 59 if (listOfHandlers != null) 60 listOfHandlers("Sorry, this car is dead..."); 61 } 62 else 63 { 64 CurrentSpeed += delta; 65 if (10 == (MaxSpeed - CurrentSpeed) 66 && listOfHandlers != null) 67 { 68 listOfHandlers("Careful buddy!"); 69 } 70 if (CurrentSpeed >= MaxSpeed) 71 carIsDead = true; 72 else 73 Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed); 74 } 75 } 76 } 77 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace CarDelegate 8 { 9 class Program 10 { 11 static void Main( string[] args ) 12 { 13 Console.WriteLine("***** Delegates as event enablers *****\n"); 14 15 Car c1 = new Car("BMW", 100, 10); 16 17 // 先绑定委托对象,稍后再注销 18 Car.CarEngineHandler handler2 = new Car.CarEngineHandler(OnCarEngineEvent2); 19 c1.RegisterWithCarEngine(handler2); 20 21 Console.WriteLine("***** Speeding up 1*****"); 22 for (int i = 0; i < 6; i++) 23 c1.Accelerate(20); 24 25 c1.UnRegisterWithCarEngine(handler2); 26 27 // 注销上一种方法,注册另一种方法 28 // 观察到两种方法的输出不一样 29 c1.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent)); 30 Console.WriteLine("***** Speeding up 2*****"); 31 for (int i = 0; i < 6; i++) 32 c1.Accelerate(20); 33 34 Console.ReadLine(); 35 } 36 37 public static void OnCarEngineEvent( string msg ) 38 { 39 Console.WriteLine("\n***** Message From Car Object *****"); 40 Console.WriteLine("=> {0}", msg); 41 Console.WriteLine("***********************************\n"); 42 } 43 44 public static void OnCarEngineEvent2( string msg ) 45 { 46 Console.WriteLine("=> {0}", msg.ToUpper()); 47 } 48 } 49 }
泛型Action<>和Func<>委托示例:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace ActionAndFuncDelegates 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 Console.WriteLine("***** Fun with Action and Func *****\n"); 14 15 // 使用泛型 Action<> 委托来指向DisplayMessage, Action<>可以指向多至16个参数 16 Action<string, ConsoleColor, int> actionTarget = 17 new Action<string, ConsoleColor, int>(DisplayMessage); 18 19 actionTarget("Action Message!", ConsoleColor.Green, 5); 20 21 // 使用泛型 Func<> 委托 22 Func<int, int, int> funcTarget = new Func<int, int, int>(Add); 23 int result = funcTarget.Invoke(40, 40); 24 Console.WriteLine("40 + 40 = {0}", result); 25 26 Func<int, int, string> funcTarget2 = new Func<int, int, string>(SumToString); 27 string sum = funcTarget2(90, 300); 28 Console.WriteLine(sum); 29 30 Console.ReadLine(); 31 } 32 33 static void DisplayMessage(string msg, ConsoleColor txtColor, int printCount) 34 { 35 // 设置命令行文本颜色 36 ConsoleColor previous = Console.ForegroundColor; 37 Console.ForegroundColor = txtColor; 38 39 for (int i = 0; i < printCount; i++) 40 { 41 Console.WriteLine(msg); 42 } 43 // 重置颜色 44 Console.ForegroundColor = previous; 45 } 46 47 static int Add(int x, int y) 48 { 49 return x + y; 50 } 51 52 static string SumToString(int x, int y) 53 { 54 return (x + y).ToString(); 55 } 56 } 57 }
在事件注册时直接将一个委托与一段代码相关联称为匿名方法。使用 +=语法处理事件时被内联定义。
如:
Car c1 = new Car("BMW", 100, 10);
c1.AboutToBlow += delegate(object sender, CarEventArgs e)
{
aboutToBlowCounter++;
Console.WriteLine("Message from Car: {0}", e.msg);
{
aboutToBlowCounter++;
Console.WriteLine("Message from Car: {0}", e.msg);
};
C#的Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。语法如下:
形参列表=>函数体
函数体多于一条语句的可用大括号括起。
Lambda 表达式可以用于任何匿名方法或者强类型委托可以应用的场合,而且比匿名方法更节省编码时间。其实编译器只是把表达式编译为使用委托Predicate<T>的标准匿名方法而已。
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace LambdaExpressionsMultipleParams 8 { 9 public class SimpleMath 10 { 11 // 多个参数 12 public delegate void MathMessage( string msg, int result ); 13 private MathMessage mmDelegate; 14 15 public void SetMathHandler( MathMessage target ) 16 { mmDelegate = target; } 17 18 public void Add( int x, int y ) 19 { 20 if (mmDelegate != null) 21 mmDelegate.Invoke("Adding has completed!", x + y); 22 } 23 } 24 25 class Program 26 { 27 static void Main( string[] args ) 28 { 29 // 使用Lambda表达式注册委托 30 SimpleMath m = new SimpleMath(); 31 m.SetMathHandler(( msg, result ) => 32 { Console.WriteLine("Message: {0}, Result: {1}", msg, result); }); 33 34 // 执行Lambda表达式 35 m.Add(10, 10); 36 Console.ReadLine(); 37 } 38 } 39 }