Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we need the "event" keyword while defining events?

Tags:

c#

.net

People also ask

What does the event keyword do?

The event keyword is used to declare an event in a publisher class.

Why do we need event in C#?

Events enable a class or object to notify other classes or objects when something of interest occurs. The class that sends (or raises) the event is called the publisher and the classes that receive (or handle) the event are called subscribers.

Is event a keyword in C++?

The event keyword lets you declare an event. An event is a way for a class to provide notifications when something of interest happens.

What keyword does C# use to wire event handlers to events?

Use "event" keyword with delegate type variable to declare an event. Use built-in delegate EventHandler or EventHandler<TEventArgs> for common events. The publisher class raises an event, and the subscriber class registers for an event and provides the event-handler method.


Field-like events and public fields of delegate types look similar, but are actually very different.

An event is fundamentally like a property - it's a pair of add/remove methods (instead of the get/set of a property). When you declare a field-like event (i.e. one where you don't specify the add/remove bits yourself) a public event is created, and a private backing field. This lets you raise the event privately, but allow public subscription. With a public delegate field, anyone can remove other people's event handlers, raise the event themselves, etc - it's an encapsulation disaster.

For more on events (and delegates) read my article on this topic. (At some point I need to update this for C# 4, which changes field-like events very slightly. The gist of it is still correct though.)


The event keyword does 3 different things:

  1. You can define an event in an interface, even though you cannot define regular fields in interfaces.
  2. It changes the visibility of the = and () operators (assignment and invocation) to private, so that only the containing class can invoke the event or override all the methods contained in it. The -= and += operators can still be invoked on an event from outside the class defining it (they get the access modifier you wrote next to the event).
  3. You can also override the way -= and += behave on events.

The other answers are fine; I'd just like to add something else to think about.

Your question is "why do we need events when we have fields of delegate type?" I would extend that question: why do you need methods, properties, events, instance constructors or finalizers if you have fields of delegate type? Why do you need anything other than fields that contain values and delegates in a type? Why not just say

class C
{
    private int z;
    public readonly Func<int, int> M = (int x)=>{ return x+z; }
    // ... and so on
}

?

You don't need methods, properties or events. We give you that stuff because the method, property and event design patterns are important and useful, and deserve to have a standard, documented, clear way to implement them in the language.


It's partly needed because if you omit the event keyword, it breaks encapsulation. If it's just a public multicast delegate, anyone can invoke it, set it to null or tamper with it. If a class called MailNotifier exists and it has an event called MailReceived, it makes no sense for other types to be able to fire that event via calling mailNotifier.MailReceived();

On the other hand, you can only meddle with and invoke 'field like' events from the type that defined it.

If you wanted to keep your event invocation private, there's nothing to stop you doing something like this:

public class MyClassWithNonFieldLikeEvent
{
   private CustomEventHandler m_delegate;

   public void Subscribe(CustomEventHandler handler) 
   {
      m_delegate += handler;        
   }

   public void Unsubscribe(CustomEventHandler handler)
   {          
      m_delegate -= handler;
   }

   private void DoSomethingThatRaisesEvent()
   {
      m_delegate.Invoke(...);
   }       
}

... but that's a whole load of code just to (more or less) do what field-like events already give us.


Events have distinct advantages compared to delegate-fields. Events can be defined in interfaces in contrast to fields, adding abstraction to the code, and even more importantly: Events can only be called from inside the defining class. In your case, anybody could call the event, possibly destroying your code.

See this blog post for further information.