【问题标题】:Delegates and Callbacks委托和回调
【发布时间】:2009-11-17 03:05:24
【问题描述】:

在委托的上下文中,术语回调是否意味着,“一个委托将它委托给另一个委托以完成某些任务”?

示例:(根据我的理解,我已经实现了回调,如有错误请指正)

namespace Test
{
    public delegate string CallbackDemo(string str);  

    class Program
    {
        static void Main(string[] args)
        {
            CallbackDemo handler = new CallbackDemo(StrAnother);
            string substr = Strfunc(handler);
            Console.WriteLine(substr);
            Console.ReadKey(true);
        }

        static string Strfunc(CallbackDemo callback)
        {
           return callback("Hello World");   
        }

        static string StrAnother(string str)
        {
            return str.Substring(1, 3).ToString();
        }
    }
}

如有必要,请提供示例。

【问题讨论】:

  • 恕我直言,将 Delegate 视为一个指向 Method 的函数指针的 Type 很有价值:就像一个 Interface 或 Class :它是一个实例的模板,它本身就是对其内部 Method 的引用:实例可以在对象之间传递并随时调用/执行。如果您有任何方法可以掌握 Jon Skeet 的“C# in Depth”,并阅读第 2 章关于代表的部分和第 5 章关于代表的部分,恕我直言,您将了解代表从“幼虫阶段”开始的“进化”在 C# 1.0 中,它们在 C# 3.0 中完全“进化”的形式。我从未找到过更好的展示方式

标签: c# callback


【解决方案1】:

你的例子是一个好的开始,但它是不正确的。您不会在方法中创建新委托,而是在类中的事件声明中使用它。请参阅您的代码的修改示例:

namespace Test
{
    //In this case, this delegate declaration is like specifying a specific kind of function that must be used with events.
    public delegate string CallbackDemo(string str);
    class Program
    {
        public static event CallbackDemo OnFoobared;
        static void Main(string[] args)
        {
            //this means that StrAnother is "subscribing" to the event, in other words it gets called when the event is fired
            OnFoobared += StrAnother;
            string substr = Strfunc();
            Console.WriteLine(substr);
            Console.ReadKey(true);
            //this is the other use of delegates, in this case they are being used as an "anonymous function". 
            //This one takes no parameters and returns void, and it's equivalent to the function declaration 
            //'void myMethod() { Console.WriteLine("another use of a delegate"); }'
            Action myCode = delegate
            {
                Console.WriteLine("another use of a delegate");
            };
            myCode();
            Console.ReadKey(true);
            //the previous 4 lines are equivalent to the following however this is generally what you should use if you can
            //its called a lambda expression but it's basically a way to toss arbitrary code around
            //read more at http://www.developer.com/net/csharp/article.php/3598381/The-New-Lambda-Expressions-Feature-in-C-30.htm or 
            //http://stackoverflow.com/questions/167343/c-lambda-expression-why-should-i-use-this
            Action myCode2 = () => Console.WriteLine("a lambda expression");
            myCode2();
            Console.ReadKey(true);
        }

        static string Strfunc()
        {
            return OnFoobared("a use of a delegate (with an event)");
        }
        static string StrAnother(string str)
        {
            return str.Substring(1, 3).ToString();
        }
    }
}

我在这里只触及了表面;搜索“delegate c#”和“lambda expression c#”的堆栈溢出以获取更多信息!

【讨论】:

    【解决方案2】:

    回调是委托在调用时执行的内容。例如,当使用委托使用异步模式时,您会执行以下操作:

    public static void Main(string[] args)
    {
        Socket s = new Socket(...);
        
        byte[] buffer = new byte[10];
        s.BeginReceive(buffer, 0, 10, SocketFlags.None, new AsyncCallback(OnMessageReceived), buffer);
    
        Console.ReadKey();
    }
    
    public static void OnMessageReceived(IAsyncResult result)
    {
        // ...
    }
    

    OnMessageReceived 是回调,通过调用委托执行的代码。有关更多信息,请参阅this Wikipedia article,或在 Google 上查看更多示例。

    【讨论】:

      【解决方案3】:

      回调基本上是传递给过程的委托,该过程将在某个适当的点“回调”。例如,在 WebRequest.BeginGetResponse 或 WCF BeginXxx 操作等异步调用中,您将传递 AsyncCallback。工作人员将“回调”您作为 AsyncCallback 传入的任何方法,在这种情况下,当它完成时让您知道它已完成并获取结果。

      事件处理程序可以被视为另一个示例。例如,当您将处理程序附加到 Click 事件时,按钮将在单击发生时“回调”到该处理程序。

      【讨论】:

        【解决方案4】:

        这会因为它是正确的原因而被否决。 C# 没有实现委托,它实现的是呼叫转发。这种不正确使用命名法可能是 C# 在这方面的最大问题。

        下面的 ACM 论文是对后来被称为委托的第一个描述。基本上,委托似乎是一个对象的实例(它的实际实现方式无关紧要)。这意味着您可以从委托中调用方法、访问属性等。

        http://web.media.mit.edu/~lieber/Lieberary/OOP/Delegation/Delegation.html

        C# 实现的是回调或呼叫转发(全取决于您如何使用它们)。这些不是代表。为了成为委托人,可以像访问对象本身一样访问对象。

        当笔将绘图消息委托给原型笔时,它是在说“我不知道如何处理绘图消息。如果可以的话,我希望你能帮我回答,但如果你还有其他问题,比如我的 x 变量的值是多少,或者需要做任何事情,你应该回来问我。”如果消息被进一步委托,所有关于变量值的问题或回复消息的请求都被推断到首先委托消息的对象。 - 亨利·利伯曼

        那么,它是怎么搞砸的呢?老实说,我不知道。我知道我早在 C# 之前就一直在使用委托(超过 16 年),而 C# 实现的不是委托。

        这里有一个很好的解释。

        http://www.saturnflyer.com/blog/jim/2012/07/06/the-gang-of-four-is-wrong-and-you-dont-understand-delegation/

        真正的委托不仅仅是创建回调或呼叫转移。一个真正的委托让我可以调用该对象的任何方法,获取和/或设置公共属性等 - 就好像它是对象本身一样。这比 C#“委托”功能强大得多,实际上也更容易使用。

        OP 问道:

        在委托的上下文中,术语回调是否意味着“一个委托将它委托给另一个委托以完成某些任务”?

        答案是肯定的。委托上下文中的回调只能用于完成某些任务。例如,您有一个从天气站点获取数据的类。由于它是非确定性的,因此在接收到(并且可能已解析)数据时实现回调会很漂亮。

        至于为什么委托被破坏,我不知道。我期待 C# 实现 TRUE 委托。

        【讨论】:

        • 谢谢。命名一直让我感到困惑,现在我明白了为什么。
        • 当您实际使用委托时,C#(以及,遗憾的是,其他人)所谓的“委托”之间的区别是显而易见的:它们根本没有实现委托。代表很容易,一点也不混乱。我目前正在处理一个使用它“认为”是“委托”但实际上是回调和呼叫转发的 API。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-16
        • 2018-09-21
        • 1970-01-01
        • 1970-01-01
        • 2023-03-10
        • 1970-01-01
        • 2011-07-08
        相关资源
        最近更新 更多