4

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

}

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

4

5 回答 5

3

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

因此,假设您有一个类控制机场中的飞机(称为它FlightTower)和许多不同的飞机。每架飞机都知道自己的一切——它应该什么时候离开,是否每个人都在飞机上——但它不知道其他飞机,或者跑道是否畅通,或者其他任何事情。

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

委托的方法是FlightTower给飞机一个检查是否起飞的方法。当飞机到达机场时,FlightTower他们会给他们一些无线电指令——他们可以问“可以起飞”,然后FlightTower会给他们一个答案。飞机不需要做任何自己考虑的事情。

委托方法的一个很酷的地方是,FlightTower当飞机提出问题时(假设它给出了正确的答案),它可以做任何它喜欢的事情。它可以自己找出答案,可以将查询发送到某个调度系统或其他任何东西。这就是委派概念的核心——平面将过程“委派”给FlightTower.

于 2013-10-16T15:48:47.217 回答
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);
    }
}

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

于 2013-10-16T14:16:26.917 回答
2

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

资料来源:堆栈交换

示例: CodeProject:代表和事件的 6 个重要用途

于 2013-10-16T14:10:03.773 回答
0

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

使用它的真实场景是在启动新线程时。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);
}
于 2013-10-16T14:29:07.860 回答
-2

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

于 2013-10-16T14:07:55.707 回答