使用特定示例了解C#中的委托和事件

时间:2012-12-30 18:22:59

标签: c# events delegates

所以我正在理解事件和代表。

我完全理解代表的用法。 关于委托的唯一问题是代理是否可以配置为以任何方式使用与事件无关的函数... 如果是,我如何为委托定义的函数编写逻辑? (我想这个功能并没有太多意义,但知道它很好。)

至于事件......我很难理解它。我认为事件是在代码中发生某些事情时执行的函数。 但是,我没有得到创建活动的过程。部分。

对于这个问题,我将使用 Gary Willoughby的答案https://stackoverflow.com/a/803528/1104766 它发布在一个问题上,我试图理解这整个主题。

我在上面的例子中没有得到什么:
MyObject.OnMaximum += new MyEventHandler(MaximumReached);
首先,如何创建委托实例,并在需要2时只传递1个变量?必须有一些我缺少的东西......
关于这一行的第二件事是new ...()实例被添加到驻留在OnMaximum的{​​{1}}函数中,MyObject是{{1}的一个实例} - 如果可以做到这一点,究竟是什么MyClass它从来没有真正定义过!

OnMaximum

至于这一部分, if(OnMaximum != null) { OnMaximum(this, new MyEventArgs("You've entered " + value.ToString() + ", but the maximum is " + Maximum.ToString())); } 被调用,但它的逻辑从未真正定义在代码中的任何地方,那么结果会是什么呢?显然我猜它是“你输入.............”的文字,但我的问题是更具体,功能的价值真正发生了什么/ event收到?

为了清晰起见,我在 BOLD 中标记了我的所有问题。

P.S,我知道这个问题一般已经发布了几次 请注意,此特定问题是指其他成员撰写的答案,此处提出的问题仅适用于此示例。这就是为什么谷歌没有真正找到这样的答案的原因 虽然有记录,我在发布之前就进行了搜索,但我确实尝试了解,但我想这些例子是我理解某些内容的最佳方式,尤其是当我对英语CS词汇的知识缺乏时。

4 个答案:

答案 0 :(得分:7)

我认为你可能患有过量的语法糖!

你看,所有活动都是代表。实际上,说实话,它是一组代表,可能是null

我们举一个例子:

public class Alarm
{
    public delegate void AlarmEvent();

    // my secret stuff

    // raise it!
    public void Ring()
    {
        if(OnAlert != null)
           OnAlert();
    }

    public event AlarmEvent OnAlert;
}

所有event关键字在这里提供,是能够添加和删除该事件的监听器......

Alarm a = new Alarm();
a.OnAlert += myevent;
a.OnAlert += myotherevent;

另一方面,代表虽然完全像我们刚才描述的那样工作,但更像是一个函数指针。想象一下一个抽象的渲染器,我可以这样做:

public abstract class Renderer
{
    protected abstract void RenderImpl();
}

这意味着,我必然会从该渲染中获得。但是如果那个渲染器拿了一个代表呢?

public abstract class Renderer
{
    public delegate void RenderDelegate();

    public Renderer(RenderDelegate) { /* ... */ }
}

我们现在正在分离出作文。

我在做什么?是好还是不好?在事件的情况下,我允许公众成为我班级的观察员。他们可以做出反应在第二种情况下,我定义了一个用户提供的委托来执行利基功能,同时我保留了大部分控制权。

代表和事件大致相同 - 但我们所做的设计选择确定哪一个是合适的。

为了解决您的其他问题,您将提出一个很好的事件与代表的例子。如果我们要更改上面的警报类,允许代理返回truefalse,那么会发生什么?

我们会让几个观察者返回真实,但谁是对的,我们该如何检查它们?

关闭单个委托路线,但是......“渲染成功”或“渲染失败”。改变这个单一代表并不是一个问题。我们可以预测地测试我们的渲染器是否完成了这项工作:

if(!delegate_->Invoke())
    fallBackCode();

我们不能用事件做到这一点。嗯,不可预测。

更简单地说,当您想要播放某些内容并让其他人在收到该事件时做某事时,会有事件发生。炸弹爆炸了......跑,躲起来,打电话给国民警卫队,关掉烤箱,或者躲避和掩护。

代表允许您在不更改模型的情况下更改功能(代表遵循签名!)。代表的一个很好的例子就是当你致电List<T>.Sort时。那是代表。它有一个签名。

但您也可以将它们用于更高级的事情,例如在不诉诸接口的情况下更改Renderer类,并且能够提供用户定义的“片段”。我想这里最简单的类比是Win32中的所有者绘制控件。无需覆盖整个类,无需提供接口并编写大量代码。只需更改在组合框中呈现项目的位。代表们是您如何实现这一目标的绝佳例子。

答案 1 :(得分:1)

答案 2 :(得分:0)

class Program
    {
        static void Main(string[] args)
        {
            Parent p = new Parent();
        }
    }

    ////////////////////////////////////////////

    public delegate void DelegateName(string data);

    class Child
    {
        public event DelegateName delegateName;

        public void call()
        {
            delegateName("Narottam");
        }
    }

    ///////////////////////////////////////////

    class Parent
    {
        public Parent()
        {
            Child c = new Child();
            c.delegateName += new DelegateName(print);
            //or like this
            //c.delegateName += print;
            c.call();
        }

        public void print(string name)
        {
            Console.WriteLine("yes we got the name : " + name);
        }
    }

答案 3 :(得分:0)

来吧伙计们!所有人都成功地复制了代表:)!

我将尝试在这里留下一个提示:一旦我在Javascript中实现了jquery ajax调用,我理解了代理人。例如:ajax.send(url,data,successcallback,failcallback)是函数的签名。如您所知,它将数据作为响应发送到服务器URL,可能是200OK或其他一些错误。如果发生任何此类事件(成功/失败),您需要执行一个功能。因此,这就像一个函数的占位符,能够在成功或失败中提及。 该占位符可能不是非常通用 - 它可能接受一组参数并且可能/可能不会返回值。这个占位符的声明,如果在C#IS CALLED DELEGATE中完成!由于javascript函数对参数的数量不严格,你只能将它们视为GENERIC占位符......但是C#有一些STRICT声明......归结为DELEGATE声明!

希望它有所帮助!