无法理解真实世界场景中代表的使用

我无法理解.NET世界中代理人的正确使用。 代表们无法解决的问题是什么? 我想知道什么情况/情况是理想的或代表使用的候选人。

我知道LINQ和Lambda表达式都在后台使用Delegates。 我知道如何创建和使用它,但我无法理解的是为什么我应该创建和使用它们?

任何真实世界的例子或经验分享都将受到高度赞赏。

更新:

我创建了以下类

using System; using System.Collections.Generic; using System.Linq; namespace Basics { public class Program { static void Main() { Flight.FlightTakeOffDelegate flightDelegate; var flights = new List { new Flight {Number = "FL001", DepartureTime = DateTime.Now, TotalCrew = 15}, new Flight {Number = "FL002", DepartureTime = DateTime.Now.AddHours(1), TotalCrew = 15}, new Flight {Number = "FL003", DepartureTime = DateTime.Now.AddHours(2), TotalCrew = 15}, }; var tower = new FlightTower(flights); // Flight 002 asking to Take off var flightAskingToTakeOff = flights.FirstOrDefault(x => x.Number == "FL002"); if (flightAskingToTakeOff != null) { Console.WriteLine(string.Format("Flight {0} \t: Okay to take off?", flightAskingToTakeOff.Number)); flightDelegate = tower.CanTakeOff; flightAskingToTakeOff.CanTakeOff = flightDelegate.Invoke(flightAskingToTakeOff); Console.WriteLine(string.Format("Flight Tower \t: {0}", flightAskingToTakeOff.CanTakeOff)); } // Flight 001 asking to Take off flightAskingToTakeOff = flights.FirstOrDefault(x => x.Number == "FL001"); if (flightAskingToTakeOff != null) { Console.WriteLine(string.Format("Flight {0} \t: Okay to take off?", flightAskingToTakeOff.Number)); flightDelegate = tower.CanTakeOff; flightAskingToTakeOff.CanTakeOff = flightDelegate.Invoke(flightAskingToTakeOff); Console.WriteLine(string.Format("Flight Tower \t: {0}", flightAskingToTakeOff.CanTakeOff)); } Console.ReadKey(); } } public class FlightTower { private readonly List _schedule; public FlightTower(List schedule) { _schedule = schedule; } public bool CanTakeOff(Flight flight) { var arrivingFlights = _schedule.Where(x => x.ArrivalTime == DateTime.Now); if (!arrivingFlights.Any()) { var flightInQueue = _schedule.FirstOrDefault(x => x.DepartureTime == _schedule.Min(c=> c.DepartureTime)); if (flightInQueue != null && flightInQueue.Number == flight.Number) { return true; } } return false; } } public class Flight { public delegate bool FlightTakeOffDelegate(Flight flight); public string Number { get; set; } public DateTime DepartureTime { get; set; } public DateTime ArrivalTime { get; set; } public int TotalCrew { get; set; } public bool CanTakeOff { get; set; } } 

}

任何人都可以看看如何在这种情况下使用代理?

我有一个人为但明确的例子。

假设您有一组消息。

 public class Message { public string Tag {get;set;} public byte[] RawData{ get;set;} } 

你从队列中得到它们。

你想要解析它们。

 public class Parser { private Dictionary> _handlers = new Dictionary> { {"Tag1", (message) => {here are parse rules}}, {"Tag2", (message) => {here are parse rules2}}, } public string Handle(Message message) { var handler = _handlers[message.Tag]; return handler(message); } } 

因此,如您所见,您可以将任何委托视为普通对象。 您可以存储集合,也可以将它们传递给其他方法等等。

代表不允许您执行您尚未执行的任务,但它们允许您使用更清晰,更模块化的代码实现相同的结果。 这个概念非常类似于generics/接口或抽象类的实现,但它适用于动作和函数,而不是对象和属性。

因此,假设你有一个机场控制飞机(称之为FlightTower ),以及许多不同的飞机。 每架飞机都知道自己 – 当它应该离开时,是否每个人都在船上 – 但它不知道其他飞机,或跑道是否清晰,或其他任何东西。

非代表方法是让每架飞机都能访问FlightTower以确定何时起飞。 它可以查看FlightTower知道的平面列表,找出它们正在做什么,甚至可以与其他平面协调。 想象一下,每架飞机都有一台连接到FlightTower系统的计算机,以检查发生了什么; 每个飞行员都需要知道如何使用该系统并找出何时可以安全使用。

代表方法是让FlightTower给飞机一个检查是否起飞的方法。 当飞机到达机场时, FlightTower会给他们一些无线电命令 – 他们可以问’可以起飞’,而FlightTower会给他们一个答案。 飞机不需要做任何考虑自己的事情。

关于委托方法的一个很酷的事情是,当飞机提出问题时, FlightTower可以做任何它喜欢的事情(假设它给出了正确的答案)。 它可以找出答案本身,它可以将查询发送到某个调度系统,或其他任何东西。 这就是代表团概念的核心 – 飞机将流程委托给FlightTower

GUI代码使用委托来处理事件,例如按钮单击,窗口移动。 使用委托允许您在事件发生时调用函数。 一个例子是将保存数据的函数链接到界面上的“保存”按钮。 单击该按钮时,它被设置为执行保存数据的function。 它在GUI编程中很有用,因为整个程序可能正在等待用户做某事,而你无法知道他们将首先做什么。 使用委托允许程序的function以这样的方式连接到UI,即用户可以以他们想要的任何方式执行操作。

来源:StackExchange

示例: CodeProject:Delegates和Events的6个重要用途

委托很像函数指针。 它是一种与方法签名匹配的类型。 委托的实例可以绑定到具有该签名的方法。 这允许您传递对方法的引用,甚至是对没有实际方法可见性的对象。

使用它的真实场景是在开始新线程时。 ThreadPool类有一个静态方法来排队新线程。 但是你需要传递一个方法来从新线程调用。 为此,需要一个委托参数:

 public static bool QueueUserWorkItem(WaitCallback callBack) 

WaitCallback是一个委托,它匹配任何带有void(对象)签名的方法:

 public delegate void WaitCallback(object state) 

所以如果你有一个方法:

 void MyMethod(object state) { } 

您可以将此方法的“指针”传递给QueueUserWorkItem,以便以后可以调用它(没有ThreadPool需要您的类的任何知识)。

 void Func() { WaitCallback wc = new WaitCallback(MyMethod) ThreadPool.QueueUserWorkItem(wc); } 

事件处理程序是委托使用的完美示例。