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

时间:2013-10-16 14:03:23

标签: c# delegates

我无法理解.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; }
}

}

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

5 个答案:

答案 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编程中很有用,因为您的整个程序可能正在等待用户做某事,而您无法知道他们将首先做什么。使用委托允许程序的功能以这样一种方式连接到用户界面,即用户可以以任何他们想要的方式做事。

Source : StackExchange

示例: CodeProject: 6 important uses of Delegates and Events

答案 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)

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