+7  A: 

A virtual event is simply one which can be overridden in a derived class.

Are you happy with the concept of a virtual property, with a getter and setter which can be overridden? If so, you can think of a virtual event in exactly the same way: instead of a getter and setter, there's an "add" operation and a "remove" operation. These can be virtual, so handled polymorphically. You implement them the same way you implement any other virtual/overridden member.

Example:

using System;

class Base
{
    public virtual event EventHandler Foo
    {
        add
        {
            Console.WriteLine("Base Foo.add called");
        }
        remove
        {
            Console.WriteLine("Base Foo.remove called");
        }
    }
}

class Derived : Base
{
    public override event EventHandler Foo
    {
        add
        {
            Console.WriteLine("Derived Foo.add called");
        }
        remove
        {
            Console.WriteLine("Derived Foo.remove called");
        }
    }
}

class Test
{
    static void Main()
    {
        Base x = new Derived();

        x.Foo += (sender, args) => {};
    }
}

Note that the event itself is not responsible for what happens when it is raised - just the add/remove side. (In C#, anyway; the CLR itself has the notion of raising, but we'll ignore that for the moment.)

You may also want to read my article on events if you're slightly hazy on the difference between an event and a delegate.

Personally I find it very rare that I want a virtual event.

Jon Skeet
If the parent class raises the overridden event, it would still be the same event, right? So if you had `class A` and `class A : B`, subscribers would subscribe to the same event of an object both if it was done as A or as B?
Svish
No - raising is entirely separate. If class A overrides the add/remove and doesn't call up to class B's add/remove, then class B's mechanism for raising the event was called, then none of the handlers would be called. Think of it all in terms of plain methods - the event provides add/remove which can be virtual, but doesn't specify anything about the semantics of raising the event.
Jon Skeet
So for it to work properly you would have to do base.add and base.remove or something? (If that exists...)
Svish
Thanks for nice link btw, will read it as soon as I get the chance :)
Svish
You'd use "base.Foo += value;" within your own add implementation, etc - if you definitely want to delegate to it.
Jon Skeet