为什么我可以使用代表使用事件?

Dee*_*Raj 8 .net c# events delegates

我知道事件总是与代表联系在一起.但是,我错过了一些事件的核心用法,并试图理解这一点.

我创建了一个简单的事件程序,如下所示,它工作得很好.

namespace CompleteRef3._0
{
delegate void someEventDelegate();

class EventTester
{
    public event someEventDelegate someEvent;

    public void doEvent()
    {
        if (someEvent != null) someEvent();
    }

}

class Program
{
    static void EventHandler1()
    {
        Console.WriteLine("Event handler 1 called..");
    }

    static void EventHandler2()
    {
        Console.WriteLine("Event handler 2 called..");
    }
    static void EventHandler3()
    {
        Console.WriteLine("Event handler 3 called..");
    }


    static void Main(string[] args)
    {
        EventTester evt = new EventTester();
        evt.someEvent += EventHandler1;
        evt.someEvent += EventHandler2;
        evt.someEvent += EventHandler3;
        evt.doEvent();
        Console.ReadKey();

    }
}
}
Run Code Online (Sandbox Code Playgroud)

我用委托替换了事件声明.那就是我替换了行公共事件someEventDelegate someEvent; someEventDelegate someEvent; 在上面的程序中,我仍然得到相同的结果.现在,我很困惑为什么我们需要使用事件,如果它只能由Delegates实现.事件的真正用途是什么?

没有事件的修改程序如下 -

namespace CompleteRef3._0
{
delegate void someEventDelegate();

class EventTester
{
    someEventDelegate someEvent;

    public void doEvent()
    {
        if (someEvent != null) someEvent();
    }

}

class Program
{
    static void EventHandler1()
    {
        Console.WriteLine("Event handler 1 called..");
    }

    static void EventHandler2()
    {
        Console.WriteLine("Event handler 2 called..");
    }
    static void EventHandler3()
    {
        Console.WriteLine("Event handler 3 called..");
    }


    static void Main(string[] args)
    {
        EventTester evt = new EventTester();
        evt.someEvent += EventHandler1;
        evt.someEvent += EventHandler2;
        evt.someEvent += EventHandler3;
        evt.doEvent();
        Console.ReadKey();

    }
}
}
Run Code Online (Sandbox Code Playgroud)

小智 7

事件的主要目的是防止订户相互干扰.如果您不使用活动,您可以:

通过重新分配委托(而不是使用+ =运算符)替换其他订户,清除所有订户(通过将委托设置为null),通过调用委托向其他订户广播.

来源:C#in a Nutshell

  • +1.赋值`someEvent = new someEventDelegate(EventHandler2)`是直接使用委托的问题.另一个链接[学习C#3.0:掌握C#3.0的基础 - 代表和事件](http://msdn.microsoft.com/en-us/library/orm-9780596521066-01-17.aspx) - 这个特殊的章节是在MSDN上可以使用,并详细介绍了这个主题. (4认同)

Cod*_*shi 7

想象一下,你有3个订阅者对你的someEvent感兴趣.他们订阅了这样的:

客户1

EventTester evt = new EventTester();
evt.someEvent += Client1Handler1;
evt.someEvent += Cleint1Handler2;
Run Code Online (Sandbox Code Playgroud)

客户2

EventTester evt = new EventTester();
evt.someEvent += Client2Handler1;
evt.someEvent += Client2Handler2;
Run Code Online (Sandbox Code Playgroud)

客户3

EventTester evt = new EventTester();
evt.someEvent += Client2Handler1;
evt.someEvent += Client2Handler2;
Run Code Online (Sandbox Code Playgroud)

现在想象另一个客户端这样做:

EventTester = null;
Run Code Online (Sandbox Code Playgroud)

客户端1,2和3将不会收到任何事件,因为您有以下代码行:

if (someEvent != null) someEvent();
Run Code Online (Sandbox Code Playgroud)

上面的代码行没有任何问题,但是使用委托有问题.

阿列克谢指出的另一个问题是:

someEvent = new someEventDelegate(EventHandler2)
Run Code Online (Sandbox Code Playgroud)

如果您有一个event客户端和其中一个客户端尝试了上述操作,则不会允许它们出现编译错误,如下所示:

在此输入图像描述


ser*_*nka 6

当然,您可以使用委托,因为在幕后,事件是包装委托的构造.

但是使用事件而不是委托的基本原理与使用属性而不是字段相同 - 数据封装.直接暴露字段(无论它们是什么 - 原始字段或委托)是不好的做法.

顺便说一句,您public在委托字段之前错过了一个关键字,以便在第二个代码段中实现.

使用第二个片段的另一个"顺便说一句":对于代表,您应该使用Delegate.Combine而不是"+ =".

  • 除最后一行外,答案很好.**为什么我们不应该在委托中使用`+`和`+ =`等等?**将它们放入语言中以使事情变得漂亮.理解`+ =`与事件(调用`add`事件访问器的语法)和`+ =`与变量(这里`x + = y`非常像`x = x)之间的区别仍然很重要+ y`其中`+`可以是委托组合,字符串连接,某种类型的算术加法或其他重载).`Delegate.Combine`的一个问题是在所有编译时都不检查类型.使用`+`检查编译时类型. (6认同)