我无法理解.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<Flight>
{
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<Flight> _schedule;
public FlightTower(List<Flight> 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; }
}
}
任何人都可以看看如何在这种情况下使用代理吗?
答案 0 :(得分:3)
我有一个人为但明确的例子。
假设您有一组消息。
public class Message
{
public string Tag {get;set;}
public byte[] RawData{ get;set;}
}
你从队列中获取它们。
你想要解析它们。
public class Parser
{
private Dictionary<string, Func<Message, string>> _handlers =
new Dictionary<string, Func<Message, string>>
{
{"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);
}
}
因此,如您所见,您可以将任何委托视为普通对象。您可以存储集合,也可以将它们传递给其他方法等等。
答案 1 :(得分:3)
代理不允许您执行您尚未执行的任务,但它们允许您使用更清晰,更模块化的代码实现相同的结果。这个概念非常类似于泛型/接口或抽象类的实现,但它适用于动作和函数,而不是对象和属性。
所以,假设你有一个机场的控制飞机(称之为FlightTower
)和许多不同的飞机。每架飞机都知道自己 - 当它应该离开时,是否每个人都在船上 - 但是它不了解其他飞机,或跑道是否清晰,或其他什么。
非代表方法是让每架飞机都能访问FlightTower
以确定何时起飞。它可以查看FlightTower
知道的平面列表,找出它们正在做什么,甚至可以与其他平面协调。想象一下,每架飞机都有一台连接到FlightTower
系统的计算机来检查发生了什么;每个飞行员都需要知道如何使用该系统并找出何时可以安全使用。
代表方法是让FlightTower
为飞机提供检查是否起飞的方法。当飞机到达机场时,FlightTower
给他们一些无线电命令 - 他们可以问'可以起飞',而FlightTower
会给他们一个答案。飞机不需要做任何考虑自己的事情。
委托方法的一个很酷的事情是FlightTower
可以在飞机问问题时做任何它喜欢的事情(假设它给出了正确的答案)。它可以找出答案本身,它可以将查询发送到某个调度系统,或其他任何东西。这就是代表团概念的核心 - 飞机将流程委托给FlightTower
。
答案 2 :(得分:2)
GUI代码使用委托处理事件,例如按钮单击,窗口移动。使用委托允许您在事件发生时调用函数。一个示例是将保存数据的函数链接到界面上的“保存”按钮。单击该按钮时,它被设置为执行保存数据的功能。它在GUI编程中很有用,因为您的整个程序可能正在等待用户做某事,而您无法知道他们将首先做什么。使用委托允许程序的功能以这样一种方式连接到用户界面,即用户可以以任何他们想要的方式做事。
答案 3 :(得分:0)
委托很像函数指针。它是一种匹配方法签名的类型。委托的实例可以绑定到具有该签名的方法。这允许您将引用传递给方法,甚至传递给不具有实际方法可见性的对象。
使用它的真实场景是在开始新线程时。 ThreadPool类有一个静态方法来排队新线程。但是你需要传递一个从新线程调用的方法。为此,需要一个委托参数:
public static bool QueueUserWorkItem(WaitCallback callBack)
WaitCallback是一个委托,它匹配任何带有void(object)签名的方法:
public delegate void WaitCallback(object state)
所以,如果你有一个方法:
void MyMethod(object state)
{
}
您可以将此方法的“指针”传递给QueueUserWorkItem,以便以后可以调用它(没有ThreadPool需要您的类知识)。
void Func()
{
WaitCallback wc = new WaitCallback(MyMethod)
ThreadPool.QueueUserWorkItem(wc);
}
答案 4 :(得分:-2)
事件处理程序是委托使用的完美示例。