Search code examples
c#eventscontravariance

In C#, are event handler arguments contravariant?


If I have a class that raises an event, with (e.g.) FrobbingEventArgs, am I allowed to handle it with a method that takes EventArgs?

Here's some code:

class Program
{
   static void Main(string[] args)
   {
      Frobber frobber = new Frobber();
      frobber.Frobbing += FrobberOnFrobbing;
      frobber.Frob();
   }

   private static void FrobberOnFrobbing(object sender,
       EventArgs e)
   {
      // Do something interesting. Note that the parameter is 'EventArgs'.
   }
}

internal class Frobber
{
   public event EventHandler<FrobbingEventArgs> Frobbing;
   public event EventHandler<FrobbedEventArgs> Frobbed;

   public void Frob()
   {
      OnFrobbing();

      // Frob.

      OnFrobbed();
   }

   private void OnFrobbing()
   {
      var handler = Frobbing;
      if (handler != null)
         handler(this, new FrobbingEventArgs());
   }

   private void OnFrobbed()
   {
      var handler = Frobbed;
      if (handler != null)
         handler(this, new FrobbedEventArgs());
   }
}

internal class FrobbedEventArgs : EventArgs { }
internal class FrobbingEventArgs : EventArgs { }

The reason I ask is that ReSharper seems to have a problem with (what looks like) the equivalent in XAML, and I'm wondering if it's a bug in ReSharper, or a mistake in my understanding of C#.


Solution

  • Maybe covariant's not the word

    Close. The word you are looking for is contravariant. Conversion of a method group to a delegate type is covariant in return type and contravariant in formal parameter types.

    Here's my blog article on the subject:

    https://learn.microsoft.com/en-us/archive/blogs/ericlippert/covariance-and-contravariance-in-c-part-three-method-group-conversion-variance

    if I have a class that raises an event, with (e.g.) FrobbingEventArgs, am I allowed to handle it with a method that takes EventArgs?

    Well, you tried it and it worked, so clearly yes. For the justification in the specification see the section helpfully entitled "Method group conversions".