Return values from __events

E

Edward Diener

I am gathering from the documentation that return values from __events are
not illegal but are frowned upon in .NET. If this is the case, does one pass
back values from an event handler via "in/out" or "out" parameters ? Or is
it simply that events are just notifications and are not interested in any
values which event handlers might be able to return ?

If the latter is the case, the event model in .NET appears to have a great
shortcoming. Let's say I have an event in a component which will normally be
occurring but which can be cancelled by a possible event handler before the
event occurs. This appears to me to be a common design idiom, which I have
used in my own non-.NET code. How does one handle this situation using
events in .NET ? I would much prefer my component's event notification to
possibly pick up this fact from some event handler and react accordingly,
but if events aren't supposed to pass back values, either via return values
or "in/out" | "out' values this idiom does not work.
 
D

Daniel O'Connell

Edward Diener said:
I am gathering from the documentation that return values from __events are
not illegal but are frowned upon in .NET. If this is the case, does one pass
back values from an event handler via "in/out" or "out" parameters ? Or is
it simply that events are just notifications and are not interested in any
values which event handlers might be able to return ?

If the latter is the case, the event model in .NET appears to have a great
shortcoming. Let's say I have an event in a component which will normally be
occurring but which can be cancelled by a possible event handler before the
event occurs. This appears to me to be a common design idiom, which I have
used in my own non-.NET code. How does one handle this situation using
events in .NET ? I would much prefer my component's event notification to
possibly pick up this fact from some event handler and react accordingly,
but if events aren't supposed to pass back values, either via return values
or "in/out" | "out' values this idiom does not work.

In most cases, you would use a member variable in the EventArgs derived
class you should be passing with the event notification. A proper event
delegate signature should be in the form name(object sender, EventArgs args)
You are pretty much free to do whatever you want in the EventArgs derived
parameter, some Framework code uses a Handled property on that class which
you can set, you could, in theory anyway, extend the class to provide a
mechanism to report back to the event server immediatly(even with another
event!), I can't say if it would be a good idea or not, but you are free to
do so.
 
E

Edward Diener

Daniel said:
In most cases, you would use a member variable in the EventArgs
derived class you should be passing with the event notification. A
proper event delegate signature should be in the form name(object
sender, EventArgs args) You are pretty much free to do whatever you
want in the EventArgs derived parameter, some Framework code uses a
Handled property on that class which you can set, you could, in
theory anyway, extend the class to provide a mechanism to report back
to the event server immediatly(even with another event!), I can't say
if it would be a good idea or not, but you are free to do so.

So essentially the suggested signature for an event is:

void MyEvent(System::Object *,MyDerivedEventArgs);

I assume that this is just a way of conforming to what the .NET framework
usually uses so that event handlers are used to handling events with this
type of signature, rather than something which is mandated.

I don't mind following it. However I have certain events where I will
manually be calling the event handlers in the delegate chain before the
event occurs and, if an event argument is set to false, it becomes a
notification back to me from the event handler that the event should not
take place, and I also stop calling the rest of the event handlers for that
event. This particular design pattern works well for something I am doing,
and it would be clearer in that case to simply have the __event be
prototyped as returning a 'bool' value for 'continue with the event or not'
than for me to add the 'bool' value to MyDerivedEventArgs.

That is why I asked the original question. I do not see anything in the CLR
which does not allow a multi-cast event to have a return value. It does say
in the specs for __delegate, which of course __event uses, that the return
value for the delegate is the return value of the last handler, which of
course makes sense. However, in my design pattern for this type of event,
where I am calling the event handlers myself, it seems that I can check the
'bool' return value from each handler, and stop if one of them is 'false'.
Is there anything in the CLR or CLS which prevents this ? If so, I will add
my 'bool' return to MyDerivedEventArgs but if not it is clearer to the event
handler if the 'bool' value is the return value for my event.
 
D

Daniel O'Connell

Edward Diener said:
So essentially the suggested signature for an event is:

void MyEvent(System::Object *,MyDerivedEventArgs); Effectivly.

I assume that this is just a way of conforming to what the .NET framework
usually uses so that event handlers are used to handling events with this
type of signature, rather than something which is mandated.

I don't mind following it. However I have certain events where I will
manually be calling the event handlers in the delegate chain before the
event occurs and, if an event argument is set to false, it becomes a
notification back to me from the event handler that the event should not
take place, and I also stop calling the rest of the event handlers for that
event. This particular design pattern works well for something I am doing,
and it would be clearer in that case to simply have the __event be
prototyped as returning a 'bool' value for 'continue with the event or not'
than for me to add the 'bool' value to MyDerivedEventArgs.

That is why I asked the original question. I do not see anything in the CLR
which does not allow a multi-cast event to have a return value. It does say
in the specs for __delegate, which of course __event uses, that the return
value for the delegate is the return value of the last handler, which of
course makes sense. However, in my design pattern for this type of event,
where I am calling the event handlers myself, it seems that I can check the
'bool' return value from each handler, and stop if one of them is 'false'.
Is there anything in the CLR or CLS which prevents this ? If so, I will add
my 'bool' return to MyDerivedEventArgs but if not it is clearer to the event
handler if the 'bool' value is the return value for my event.

It is a pattern that should be followed when possible. Its often clearer to
users because most other events(if not all) follow it. I think FxCop will
complain about events not in that pattern as well.

While returning bool is clearer in a classic sense(C++ or a procedural
language for example), its not generally proper in the .NET strata, and may
not be as clear as it seems. People who have been using the framework for a
long time may be forced to double take due to the unexpected return value.
I've made the same mistake, with an out parameter, it turned out to not be
as straightforward to use as I figured it would be. I suggest sticking with
the existing pattern.
Anyway, to be clear, it should work at the CLR level. I don't know if it is
compliant with the CLS or not, but there is nothing I know of that will
block it from compiling. I do know its against class library guidelines, but
such a discussion is out of scope here. Reposting about that in
microsoft.public.dotnet.general would likely produce more varied and
interesting replies.
 
E

Edward Diener

Daniel said:
It is a pattern that should be followed when possible. Its often
clearer to users because most other events(if not all) follow it. I
think FxCop will complain about events not in that pattern as well.

While returning bool is clearer in a classic sense(C++ or a procedural
language for example), its not generally proper in the .NET strata,
and may not be as clear as it seems. People who have been using the
framework for a long time may be forced to double take due to the
unexpected return value.

Yes, I can understand this. Yet a design pattern which allows an event
handler for an upcoming event to essentially cancel the event, by
'returning' a bool false value, seems not to have been in the consideration
of the .NET designers. In fact the general explanation for reacting to
events is that the event is just a notification and if the event handler
wants to do anything in regard to this event with the object generating the
event, it needs to access the object directly through the sender parameter.
This seems unnecessarily complicated to me. The idea that an event handler
should never affect the event itself through the event handler parameters
seems too simplistic. Of course there is nothing stopping me from designing
my own events. But I really wish that some of the discussions regarding
events in the MSDN doc had acknowledged the fact that event handlers might
want to cancel or alter the event itself.
I've made the same mistake, with an out
parameter, it turned out to not be as straightforward to use as I
figured it would be. I suggest sticking with the existing pattern.
Anyway, to be clear, it should work at the CLR level. I don't know if
it is compliant with the CLS or not, but there is nothing I know of
that will block it from compiling. I do know its against class
library guidelines, but such a discussion is out of scope here.
Reposting about that in microsoft.public.dotnet.general would likely
produce more varied and interesting replies.

Thanks for your reply. I will probably follow the standard guidelines even
if it goes against my sense of design in this case. I have looked at the CLS
specification and there is nothing there which specifies anything about the
types in the method signature for an event other than that the types
themselves must be CLS compliant. Neverthless, who am I to upset the status
quo <g> . Actually the guidelines are decent as having a structure to pass
event arguments is simpler than having a series of parameters, if less
understandable in general.
 
D

Daniel O'Connell

Yes, I can understand this. Yet a design pattern which allows an event
handler for an upcoming event to essentially cancel the event, by
'returning' a bool false value, seems not to have been in the consideration
of the .NET designers. In fact the general explanation for reacting to
events is that the event is just a notification and if the event handler
wants to do anything in regard to this event with the object generating the
event, it needs to access the object directly through the sender parameter.
This seems unnecessarily complicated to me. The idea that an event handler
should never affect the event itself through the event handler parameters
seems too simplistic. Of course there is nothing stopping me from designing
my own events. But I really wish that some of the discussions regarding
events in the MSDN doc had acknowledged the fact that event handlers might
want to cancel or alter the event itself.
There is no particular discussion I know of, something like [1] is the model
I'd use. Also, by allowing all your event properties to be settable, ideally
a event handler could modify the event data easily. However, you should look
into event ordering. As far as I know, there is no guarentee that an event
will be called in any predictable order, without that a handler that changes
events may end up being called last. Unless there is a guarentee its
something I'd be hesitant to rely on.
Thanks for your reply. I will probably follow the standard guidelines even
if it goes against my sense of design in this case. I have looked at the CLS
specification and there is nothing there which specifies anything about the
types in the method signature for an event other than that the types
themselves must be CLS compliant. Neverthless, who am I to upset the status
quo <g> . Actually the guidelines are decent as having a structure to pass
event arguments is simpler than having a series of parameters, if less
understandable in general.
Yeah, its a little strange, but allows for proper OO behaviour. You don't
have to pass a concrete derived event args, but you could possibly pass an
extended one that handlers can test for, etc. Its not always advisable, but
it is possible.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top