在C#(或其他语言)中使用委托

在C#(或其他语言)中使用委托,c#,.net,delegates,C#,.net,Delegates,我一直想知道,代表如何发挥作用,我们为什么要使用他们?除了类型安全和VisualStudio文档中的所有这些优点之外,委托的实际用途是什么 我已经找到了一个,而且很有针对性 using System; namespace HelloNamespace { class Greetings{ public static void DisplayEnglish() { Console.WriteLine("Hello, world!"); }

我一直想知道,代表如何发挥作用,我们为什么要使用他们?除了类型安全和VisualStudio文档中的所有这些优点之外,委托的实际用途是什么

我已经找到了一个,而且很有针对性

using System;

namespace HelloNamespace {

    class Greetings{
    public static void DisplayEnglish() {
            Console.WriteLine("Hello, world!");
    }
    public static void DisplayItalian() {
             Console.WriteLine("Ciao, mondo!");
    }
    public static void DisplaySpanish() {
             Console.WriteLine("Hola, imundo!");
         }
    }

    delegate void delGreeting();

    class HelloWorld {
        static void Main(string [] args) {

    int iChoice=int.Parse(args[0]);
    delGreeting [] arrayofGreetings={
             new delGreeting(Greetings.DisplayEnglish),
             new delGreeting(Greetings.DisplayItalian),
             new delGreeting(Greetings.DisplaySpanish)};

    arrayofGreetings[iChoice-1]();
         }
    }
}
但这并没有确切地告诉我使用委托而不是解析参数并运行方法的条件“If…{}”的优点

有人知道为什么在这里使用delegate比“if…{}”更好吗。您是否还有其他示例证明学员的有用性


谢谢

委托是一种将功能注入方法的好方法。正因为如此,它们大大有助于代码重用

想想看,假设您有一组相关的方法,它们具有几乎相同的功能,但仅在几行代码上有所不同。您可以将这些方法的所有共同点重构为一个方法,然后通过委托将专门的功能注入其中


以LINQ使用的所有IEnumerable扩展方法为例。它们都定义了公共功能,但需要一个委托传递给它们,以定义返回数据的投影方式,或数据的过滤、排序方式等。

在C#中,委托最常见的日常使用是事件处理。当您在WinForm上有一个按钮,并且希望在单击该按钮时执行某些操作时,您所做的就是注册一个代理函数,以便在单击该按钮时由该按钮调用

所有这些都是在VisualStudio本身生成的代码中自动在后台发生的,因此您可能看不到发生的位置


一个现实世界中可能对您更有用的案例是,如果您希望创建一个人们可以使用的库,该库将从Internet提要读取数据,并在提要更新时通知他们。通过使用委托,使用您的库的程序员可以在提要更新时调用自己的代码。

Lambda expressions
代表主要与活动一起使用。但动态语言显示了其更广泛的用途。这就是为什么在我们拿到C#3.0之前,代表们都没有充分利用。使用Lambda表达式(生成委托方法)很容易做一些事情

现在假设你有一个IEnumerable的字符串。您可以轻松定义委托(使用Lambda表达式或任何其他方式),并将其应用于每个元素(例如修剪多余的空间)。并且在不使用循环语句的情况下执行。当然,您的委托可能会执行更复杂的任务。

委托用于“调用”其他类中的代码(这些类可能不一定在同一个类、类或.cs甚至同一个程序集中)

在您的示例中,可以简单地用您指出的if语句替换委托


但是,委托是指向代码中某个“存在”的函数的指针,例如,由于组织原因,您无法(轻松)访问这些函数。

我发现另一个好处是,如果我希望执行相同的操作,在同一对象类型的多个实例中传递相同的数据或触发相同的操作。

我将尝试列出一些超出简单if-else场景的示例:

  • 实现回调。例如,您正在解析XML文档,希望在遇到特定节点时调用特定函数。您可以将委托传递给函数

  • 实施战略设计模式。将学员分配给所需的算法/策略实施

  • 如果希望在单独的线程上执行某些功能(此函数没有任何要发送回主程序的内容),则为匿名委托

  • 其他人建议的事件订阅


  • 在您的示例中,您的变灰是相同的,所以您实际需要的是字符串数组

    如果您希望在命令模式中使用委托,请想象您有:

    public static void ShakeHands()
    { ... }
    
    public static void HowAreYou()
    { ... }
    
    public static void FrenchKissing()
    { ... }
    
    您可以用相同的签名替换方法,但操作不同。
    你选择了一个太简单的例子,我的建议是-去寻找一本C#Depth的书。

    在.NET中,从后台线程更新UI时也需要代理。由于无法从不同于创建控件的线程更新控件,因此需要在创建线程的上下文中调用更新代码(主要使用此.invoke)。

    委托和相关语法糖已显著改变了C#world(2.0+) 委托是类型安全的函数指针-因此您可以在将来某个时间点调用/执行代码块的任何位置使用委托

    我能想到的主要部分

    回调/事件处理程序:在发生EventX时执行此操作。或者在准备好异步方法调用的结果时执行此操作

    myButton.Click += delegate { Console.WriteLine("Robbery in progress. Call the cops!"); }
    
    LINQ:元素的选择、投影等,您希望在将每个元素传递到管道之前对其进行处理。e、 g.选择所有偶数,然后返回每个偶数的平方

    var list = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
                     .Where(delegate(int x) { return ((x % 2) == 0); })
                     .Select(delegate(int x) { return x * x; });    
    // results in 4, 16, 36, 64, 100
    

    这是一个真实的例子。在包装某种外部呼叫时,我经常使用委托。例如,我们有一个旧的应用程序服务器(我希望它会消失),我们通过.NETRemoting连接到它。我将通过“safecall”函数在代理中调用应用程序服务器,如下所示:

    private delegate T AppServerDelegate<T>();
    
    private T processAppServerRequest<T>(AppServerDelegate<T> delegate_) {
               try{
                  return delegate_();
               }
               catch{
                  //Do a bunch of standard error handling here which will be 
                  //the same for all appserver  calls.
               }
    
            }
    
    //Wrapped public call to AppServer
    public int PostXYZRequest(string requestData1, string requestData2, 
       int pid, DateTime latestRequestTime){
               processAppServerRequest<int>(
                  delegate {
                     return _appSvr.PostXYZRequest(
                        requestData1, 
                        requestData2, 
                        pid, 
                        latestRequestTime);  
                  });
    
    private委托T AppServerDelegate();
    私有T进程AppServerRequest(AppServerDelegate委托){
    试一试{
    返回委托_();
    }
    抓住{
    //在这里做一些标准的错误处理
    //所有appserver调用都是相同的。
    }