Must event delegates follow the "conventional" form?

  • Thread starter Thread starter Jeff Brown
  • Start date Start date
J

Jeff Brown

More than once in the .NET documentation, they say, "By convention, event
delegates in the .NET Framework have two parameters: The source that raised
the event, and the data for the event [which is an instance of the EventArgs
class, or of a class that's derived from EventArgs]."

It seems that this convention results in twice as much work whenever we have
custom arguments for an event handler. Specifically, we must define:

1. A custom data class, which is derived from EventArgs; and

2. (for maximum type safety) A custom event delegate, which takes an
instance of the aforementioned data class as its second argument.

On the other hand, if we DON'T follow the convention, then we can simply
define:

1. A custom event delegate whose arguments are simply the custom data
values, listed directly.

Does anyone know: Is there any TECHNICAL reason that we should follow the
convention? In other words, is there any aspect of the .NET framework that
DEPENDS upon the convention being followed?

Thanks,
Jeff Brown
 
Does anyone know: Is there any TECHNICAL reason that we should follow the
convention? In other words, is there any aspect of the .NET framework that
DEPENDS upon the convention being followed?

No, there is nothing that forces it.

The benefit comes in that adding new parameters does not require changing
the signature of every subscriber.
 
Hi,
Does anyone know: Is there any TECHNICAL reason that we should follow
the convention? In other words, is there any aspect of the .NET
framework that DEPENDS upon the convention being followed?

If I remember well, events complying with that convention benefit from
some optimizations from the framework and / or from the compiler. Also,
there *are* good technical reasons for following this convention.
Quoting Shawn Burke from MS:

"
The .NET architecture certainly allows you to define your delegate
signatures any way you like. When you write your software, you're
certainly entitled to do so.

When we went about the business of writing a collection of objects as
large as the .NET Framwork, we knew from the beginning that consistancy
was important. As a developer, it really bothers me when pieces of the
same product look and act completely differently. So we sat down and
crafted a set of what design guidelines or "design patterns" that our
classes should conform to. The idea is that a user should be able to
move among the different areas of the .NET Framework as easily as
possible. One way to do that is to have common naming, eventing, and
signature types across the framework. The decisions we made usually
had solid technical reasons behind them, but that doesn't mean there are
other vialble options or better solutions for specific problems.

In the case of event handlers, we established the pattern you see for a
couple of reasons:

1) Ease of calling and defining (simplicity). The more parameters we
had, the more a user has to type to create a handler for them. Think
about when you need to override a function with a whole bunch of
arguments. It's kind of a pain to type out all those paramaters when you
may not be interested in handling them

2) Reusability. By keeping the signatures consistant, we increased the
likelyhood that we wouldn't need yet another class of handlers for a
given type of event -- reuse is good since it keeps namespaces smaller,
has need for less documentatoin, etc.

3) Modifyable values. Many of our *EventArg classes have data in them
that can be specified or modified by the event handlers. For example.
the KeyEventArgs class has a read/write Handled property that can be set
to "true" by handler function if the key should not be passed to the
default handler and processing stopped. You can't do this with normal
params (unless they're passed byref which just adds a little more
complexity.

4) Extensibility. Having a base class allows us to add functionality (we
don't have plans for this, but if push came to shove it's an option)
without breaking people. Hypothetically, say users were screaming for
the new size in the Resize event, which is currently just a plain
EventHandler. Well, we could derive a ResizeEventArgs from EventArgs and
pass that into the existing handler without breaking anybody's code.
Folks that cared about it could check the type, do a cast, and get the
extended info.
"
 
There's also a good discussion of this topic in the MSDN:

Basic Instincts: Programming Events of the Framework Class Libraries
 
Back
Top