Why do I need a null test before I invoke a delegate?

Published 19 March 04 08:41 PM

Q: Why do I need a null test before I invoke a delegate?

A: If you have an event in a class, you need to add a null test before you call the delegate. Typically, you would write:

if (Click != null)
    Click(arg1, arg2);

There is actually a possible race condition here - the event can be cleared between the first and second line. You would actually want to write:

ClickHandler handler = Click;

if (handler != null)
    handler(arg1, arg2);

usually. You might want to do some other sort of synchronization in other scenarios.

So back to the main question. Why is the null test required?

We can't change the existing behavior of calling through a delegate as some apps may depend on it, so it would have to be an addition to the language.

We have talked about adding an Invoke() keyword to the language to make this easier, but after a fair bit of discussion, we decided that we couldn't do the right thing all the time, so we elected not to do anything.

[Author: Eric Gunnerson]

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Zee said on March 19, 2004 8:58 PM:
Not finished?
# Luke Stevens said on March 19, 2004 9:25 PM:
I think the confusing part is that with events, you can have one or three or zero handlers, but it seems that someone goes through a lot of extra trouble to make the zero case behave like null. You would not, for example, expect a zero-length array to behave like null.

And can we really depend on the copying (it is by value, right?) to be atomic?
# Richard Blewett said on March 20, 2004 4:14 AM:
The assignment is simply a copy of the reference to the delegate instance, not a by-value copy. It caches a reference in case another thread (or piece of re-entrant code) nulls out the reference before it invokes it.
# Roy J. Salisbury said on March 20, 2004 1:50 PM:
Yes, I believe you can count on the assignemnet opperation being atomic. I'm missing half the article, but can only assume that you are talking aobut doing something like this:

MyDelegate myTempHandler = myHandler;
if (myTempHandler != null) {
myTempHandler(arg1, arg2);
}

# thomas.drakengren@cainetech.com (Thomas Drakengren said on March 21, 2004 7:42 AM:
Copying the event before testing and invoking isn't always good enough, in the multithreaded case. Sometimes you want a client to unregister its event handler, and to be sure that the event handler isn't called on the source line after the "unregister" call. (Perhaps the client will kill some resource used by the event handler, for instance.) That won't work with copying before testing and invoking.
# Thomas Eyde said on April 2, 2004 2:15 AM:
If you change the behaviour of the event handler to never be null, how would it break existing code? Old clients would keep their null tests, new client don't have to add them.

I agree with Luke. It's strange that you can do a += operation on a null, then it's not null anymore, and if you do a -= enough times, then you suddenly have a null.

Why don't you just treat the event like the collection of listeners it is???
# Ray Moody said on April 20, 2004 11:28 AM:
Why can't there be multicast delegates with an empty invocation list?

If multicast delegates with empty invocation lists existed, we could initialize up our member variables with them. Then, since we could prove that the member variables were never null, we wouldn't have to test for it.

For example:

public class C
{
// Won't compile, but I sure wish it would.
public EventHandler click = new EventHandler();

public FireClick()
{
click(this, null);
}
}
# Kael Rowan said on April 21, 2004 11:29 AM:
Ray, you could do something similar with anonymous delegates. Just initially add an empty method inline as a handler at creation and never remove it. I wouldn't personally use it in my own code due to the fact that it would be inefficient at runtime since you'd always be invoking the empty method for no reason, but it would make the code everywhere else cleaner and be a nifty trick ;)
# jaybaz [MS] said on June 17, 2004 2:31 PM:
I was all excited about this new idea I just had, but it turns out that Kael beat me by 2 months.

I'm not concerned about the perf hit, until I get some perf data back that says I should be.

http://blogs.msdn.com/jaybaz_ms/archive/2004/06/17/158636.aspx
# ok said on July 18, 2004 12:30 AM:
my web:
http://www.sj55.com/pic_sort http://www.zw88.com/paopaotang.htm http://www.zw88.com/sj.htm http://www.zw88.com/sm/
http://www.zw88.com/sms/ http://www.zw88.com/zw.htm http://www.resou.com/8888.htm http://www.sj55.com/pic/pic_1130.htm
# RebelGeekz said on December 28, 2004 4:54 AM:
[http://itpeixun.51.net/][http://aissl.51.net/][http://kukuxz003.freewebpage.org/][http://kukuxz001.51.net/][http://kukuxz003.51.net/][http://kukuxz005.51.net/][http://kukuxz002.51.net/][http://kukuxz004.freewebpage.org/][http://kukuxz007.51.net/][http://kukuxz001.freewebpage.org/][http://kukuxz006.51.net/][http://kukuxz002.freewebpage.org/][http://kukuxz004.51.net/][http://kukuxz008.51.net/][http://kukuxz009.51.net/][http://kukuxz005.freewebpage.org/][http://kukuxz006.freewebpage.org/][http://kukuxz007.freewebpage.org/][http://kukuxz009.freewebpage.org/]
# c# 2.x feature requests | keyongtech said on January 22, 2009 12:43 AM:

PingBack from http://www.keyongtech.com/651205-c-2-x-feature-requests

Leave a Comment

(required) 
(optional)
(required) 

  
Enter Code Here: Required

This Blog

Syndication

Page view tracker