C# - 事件关键词优势? [英] C# - Event keyword advantages?

查看:136
本文介绍了C# - 事件关键词优势?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近才明白,C#的事件真的是。这真的不是真的,老实说。总结一下我的调查结果: 关键字只是一个修饰符,只适用于代表。



事件的所有魔法都是代表的操作。而已。我已经阅读了许多Microsoft文档,但没有一句简洁的总结如此简洁的句子。为了继续我的发现,代理,类和结构体都在同一个级别上。它们是定义对象的方法。我不是像类型中的对象,而是包含东西的概念。就像在面向对象编程 中使用'object'一样。



无论如何,'对象'有某些修饰符。例如,密封,只读,虚拟,静态等... 可以在这里。在代理的情况下,它有额外的一个称为事件。事件使得当代理被声明为类的一部分时,它只会根据提供给事件的访问修饰符公开 add 删除方法。这些方法的定义与属性的 get 设置类似。委托的其他操作(分配,读取访问,方法调用等)只能在声明事件委托的类中允许。我觉得有趣的是,所有的代理都有Invoke,BeginInvoke和EndInvoke方法,但是你无法浏览到Visual Studio中查看它们,也没有找到描述它们的文档...



好的所以知道之后,除了修改代表如何访问之外,使用event关键字有什么优势?好像在很多情况下,我最好只是简单地声明一个委托没有事件关键字。最近遇到的情况是我想创建一个包含2个事件的抽象基类。从这个基类派生的任何类应该能够使用像它们自己的类似的事件,类似于暴露给派生类的类的任何其他对象(也称为非私有的),除非派生类在另一个程序集,对象被声明为内部)。



基本上,我希望派生类使用这些事件作为自己的。唯一的方法是将事件的后备变量公开为受保护的,因此派生类可能引发事件。看看代码,这似乎很愚蠢,因为我基本上定义了两次代表;一次作为保护区,另一个作为公共事件。我想,


我不会更好地做一个名为Event的类,其中有一个
参数的Action构造函数?返回的操作等同于许多已经作为代理的扩展方法的升高,它会检查代理是否为空,然后调用委托。 Event上唯一的公共方法是添加和删除以添加代理,并从底层代理(+ =, - =)中删除它们。类可以将这些事件作为属性,例如




  public Event SomethingHappened {get;私人集合




只有该类才能重新分配事件。或者一个公开的只读字段将是一样有效。从构造函数返回的out参数由类存储,并在类想要引发事件时调用。我知道这是一个hokey解决方法,但它将完成工作,并允许事件不仅作为参数传递,而且允许派生类在基类定义为受保护的情况下调用Raise方法。


TLDR:



除修改之外,使用event关键字有什么优势如何访问代表?


解决方案


使用除修改代表如何访问?


是使用event关键字的主要优点。您仅使用一个原始代理来使用事件来阻止委托被调用或从其定义的类的范围之外被清除,因为在事件的情况下,该类负责调用该事件。外部实体不应该直接调用它们(它们可以并且应该间接地调用事件),也不应该关心是否有任何其他事件处理程序或参与触摸它们(例如,通过分配一个完全的新的代表到现场)。



想要允许子类触发事件的具体情况通常是通过定义事件的类创建一个不起作用的保护方法来解决的事件。按照惯例,这样的方法将与事件具有相同的名称,但是在On前缀。



是的,您可以创建自己的类型,逻辑上表示一个事件,是一个委托的包装器,并将可以对该事件执行的功能限制为应该能够执行它们的功能(可能使用略微不同于C#事件的规则关键字使用,这是常用于没有事件关键字(或甚至代表)的其他语言的C#设计师简单地认识到这是一个非常常见的模式,并认为将该关键字添加到语言中是有用的,以帮助最小化创建逻辑事件所需的样板代码。



使用事件关键字的另一个好处是,将某种类型的委托作为属性而不是使您的意图更清晰,如果我只看到一个委托财产隐含通常它代表一种方法。是的,C#中的所有代表都是多播代理,所以这不是真的,但是人们在事件之外利用这个功能是不寻常的。人们认为 Action 表示一个操作,而不是一个操作列表。事件也对C#文档有特殊待遇。它们都是单独列出的,它们在视觉工作室等中有不同的图标。这一切都有助于使成员的意图和语义更清晰地显示给使用该课程的人一目了然。



最后,事件关键字确保在多个线程之间存在同步,这不是由 Delegate执行类。如果多个线程同时向事件添加处理程序,则事件关键字确保两者都被添加。如果你只是公开公开一个委托,一个可以覆盖另一个由于竞争条件,并有一个处理程序最终丢弃在地板上。如果你自己的事件类你可以提供这个功能,但它是更多的样板代码和一些很容易弄乱的东西(或者导致离开竞争条件,或过多的同步导致性能下降)。


I've come to recently understand that a C# 'event' really is. It isn't really anything, honestly. To sum up my findings: The event keyword is simply a modifier that only applies to delegates.

So, all the 'magic' of an event are the operations of a delegate. That's it. I've read through a lot of the Microsoft documentation, but there no sentence that summarizes in that manner so succinctly. To continue with my findings, delegate, class, and struct are all on the same 'level'. They are ways to define a 'object'. I don't mean 'object' as in the type, but an encapsulated concept of 'something'. Like how the word 'object' is used when saying object oriented programming.

Anyway, 'objects' have certain modifiers. For example, sealed, readonly, virtual, static, etc... This list can be found here. In the case of a delegate, it has the extra one called event. Event makes it so that when a delegate is declared as part of a class, it only exposes the add and remove methods as per the access modifier given to the event. These methods are defined in a similar nature to get and set of a property. Other operations of the delegate (assignment, read-access, method invocation, etc) are only allowed within the class in which the event delegate was declared. The other thing I find interesting, is that all delegates have the methods Invoke, BeginInvoke, and EndInvoke, yet you cannot navigate to view them within Visual Studio, nor could I find the documentation describing them...

Okay. So after knowing all that, what is the advantage of using the event keyword other than for modifying how the delegate can be accessed? It seems like, in many cases, I'd be better off simply declaring a delegate without the event keyword. A situation I ran into recently is that I wanted to create an abstract base class that contained 2 events. Any class that derived from this base class should be able to use the events like they are their own, similar to any other object of the class that is exposed to the derived class (aka, non-private, unless the derived class is in another assembly, and the object was declared internal).

Basically, I wanted the derived classes to use these events as their own. The only way to do this was to expose the backing variable of the events as protected, so the derived classes could raise the events. Looking at the code, this seemed pretty stupid since I was basically defining the delegate twice; once as a protected field, and the other as the public event. I thought,

Wouldn't I be better off making a class called Event that has an out parameter of an Action in the constructor? The action that is returned is equivalent to Raise that many have made as an extension method for delegates, where it checks to see if the delegate is null, and then invokes the delegate. The only public methods on Event would be Add and Remove for appending delegates and removing them from the underlying delegate (+=, -=). Classes could have these events as properties, such as,

public Event SomethingHappened { get; private set; }

so that only that class can re-assign the event. Or a public readonly field would be just as effective. The out parameter that is returned from the constructor is stored by the class and called when the class wants to raise the event. I know it is a hokey workaround, but it'll get the job done, and allows the events to not only be passed as arguments, but allow derived classes to call the Raise method if the base class defines it as protected.

TLDR:

What is the advantage of using the event keyword other than for modifying how the delegate can be accessed?

解决方案

What is the advantage of using the event keyword other than for modifying how the delegate can be accessed?

That is the primary advantage of using the event keyword. You use an event over just a raw delegate to prevent the delegate from being invoked or cleared from outside the scope of the class it is defined in, because in the case of events it is the responsibility of that class to invoke the event. External entities shouldn't be invoking it directly (they can and should be invoking the event indirectly), nor should they "care" about whether there are any other event handlers or be involved in touching them (by, for example, assigning an entirely new delegate to the field).

The specific case of wanting to allow sub-classes to fire the event is most commonly solved by having the class that defines the event creating a protected method that does nothing but fire the event. Such methods will, by convention, have the same name as the event but with "On" prefixing it.

Yes, you could create your own type that logically represents an event, is a wrapper for a delegate, and limits the functions that can be performed on that event to those that "should" be able to perform them (possibly using slightly different rules than the C# event keyword uses. This is something that is frequently used in other languages that don't have an event keyword (or possibly even delegates). The C# designers simply realized that this was a very common pattern, and felt that it was worth the energy to add the keyword to the language to help minimize the boilerplate code required to create a logical "event".

Another benefit of using the event keyword, as opposed to just having some type of delegate as a property, is that you make your intentions much clearer. If I see just a delegate property the implication is generally that it represents one method. Yes, all delegates in C# are multicast delegates, so that's not true, but it's unusual for people to leverage that functionality outside of events. People think that an Action represents one action, not a list of actions. Events also have special treatment with respect to the C# documentation. They are all listed separately, they have different icons in visual studio, etc. This all helps make the intentions and semantics of the member much clearer to someone using the class at a glance.

Finally, the event keyword ensures that there is synchronization between multiple threads, which isn't performed by the Delegate class. If multiple threads go to add handlers to an event at the same time, the event keyword ensures both are added. If you just publicly expose a delegate it's possible for one to overwrite the other due to a race condition and have one handler end up dropped on the floor. If you roll your own Event class you could provide this functionality, but it is both more boilerplate code and something that's pretty darn easy to mess up (either resulting in leaving race conditions in, or excessive synchronization resulting in lost performance).

这篇关于C# - 事件关键词优势?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆