473,385 Members | 1,396 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Raising events

Can someone explain why this code DOES NOT raise a null reference exception?
//////////////////////////// Program.cs
/////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using CSharpLib;

namespace CSharpConsole
{
class Program
{
private EventHandler handler;
private Class1 obj;

static void Main(string[] args)
{
(new Program()).RunTest();
Console.ReadKey(true);
}

private Program()
{
obj = new Class1();
handler = new EventHandler(DoSomething);
}

private void RunTest()
{
obj.SomeEvent += handler;

obj.RaiseEvent(delegate { obj.SomeEvent -= handler; });
}

private void DoSomething(object sender, EventArgs e)
{
Console.WriteLine("foo");
}
}
}
//////////////////////////// Class1.cs
/////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;

namespace CSharpLib
{
public class Class1
{
public event EventHandler SomeEvent;

public delegate void Callback();

public Class1()
{
}

public void RaiseEvent(Callback callback)
{
EventHandler temp = SomeEvent;

callback();

if (temp != null)
{
temp(this, EventArgs.Empty);
}
}
}
}


Oct 28 '06 #1
9 1809
"CuriousGeorge" <***@***.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
Can someone explain why this code DOES NOT raise a null reference
exception?
Because no nulls are referenced?

If you have reason to believe that a null reference exception should occur,
then the least you could do is explain in your post:
a) why it is you want to execute code like this, and
b) why and where it is that you think a null reference exception would
occur

Pete
Oct 28 '06 #2
Hi,

Where do you expect a null reference exception to be raised?

This line is checking to make sure temp is not null before it's used in
Class1:

if (temp != null)

--
Dave Sexton

"CuriousGeorge" <***@***.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
Can someone explain why this code DOES NOT raise a null reference exception?
//////////////////////////// Program.cs
/////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;
using CSharpLib;

namespace CSharpConsole
{
class Program
{
private EventHandler handler;
private Class1 obj;

static void Main(string[] args)
{
(new Program()).RunTest();
Console.ReadKey(true);
}

private Program()
{
obj = new Class1();
handler = new EventHandler(DoSomething);
}

private void RunTest()
{
obj.SomeEvent += handler;

obj.RaiseEvent(delegate { obj.SomeEvent -= handler; });
}

private void DoSomething(object sender, EventArgs e)
{
Console.WriteLine("foo");
}
}
}
//////////////////////////// Class1.cs
/////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Text;

namespace CSharpLib
{
public class Class1
{
public event EventHandler SomeEvent;

public delegate void Callback();

public Class1()
{
}

public void RaiseEvent(Callback callback)
{
EventHandler temp = SomeEvent;

callback();

if (temp != null)
{
temp(this, EventArgs.Empty);
}
}
}
}


Oct 28 '06 #3
Because no nulls are referenced?
Hmmm. OK.

a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.

b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than that
its a pretty vanilla type.

As we know and event with no subscribers is actually a null-reference hence
the check for nullility before invoking the subscribed handlers.

If you in-line the delegate call in my original post you get something like
the following (compiled in Outlook Express)

public void RaiseEvent(Callback callback)
{
EventHandler temp = SomeEvent;

SomeEvent -= theOnlyRegisteredEventHandler
//SomeEvent is now null

if (temp != null)
{
temp(this, EventArgs.Empty);
}
}

The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:12*************@corp.supernews.com...
"CuriousGeorge" <***@***.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
>Can someone explain why this code DOES NOT raise a null reference
exception?

Because no nulls are referenced?

If you have reason to believe that a null reference exception should
occur, then the least you could do is explain in your post:
a) why it is you want to execute code like this, and
b) why and where it is that you think a null reference exception would
occur

Pete

Oct 28 '06 #4
Hi,
a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.
I don't see anything particularly thread safe about your code, are you
talking about checking for null that makes this thread safe? It is safe for
a single thread but once you have multiple threads the really only safe way
is to make sure you have locks in place around adding/removing delegates to
your event and the invocation of that event i.e. the following is an example
of how two threads accessing the same event can cause a null reference
exception:

using System.Threading;

namespace CSharpConsole
{
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.Run();
}
}

class TestClass
{
private delegate void MyEventHandler();
private event MyEventHandler MyEvent;

public TestClass()
{
}

public void Run()
{
Thread threadA = new Thread(new ThreadStart(ThreadADoSomething));

//Add listener to the event
MyEvent += new MyEventHandler(DoSomething);

if (MyEvent != null)
{
//got in here, let the other thread run and wait until it
//completes
threadA.Start();
threadA.Join();

//whoops now this is null
MyEvent();
}
}

void ThreadADoSomething()
{
//removes the only listener
MyEvent -= new MyEventHandler(DoSomething);
}

void DoSomething()
{
}
}
}
b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than that
its a pretty vanilla type.
There is a little bit more to this type, hence your posting :-) If you look
at the documentation for the delegate type you will see: "Delegates are
immutable; once created, the invocation list of a delegate does not change."
Hence the reason why when you assign you event (which is really just
syntactic sugar around delgates) to your other delegate type really you have
just made a new copy of that delegate. The contents of the
multicastdelegates invocation list inside the temp variable will therefore
not change when you update the other multicastdelegate through the SomeEvent
enty point.

The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
Why not just ask the question you want to ask :-)
--
http://www.markdawson.org
Posted from Windows Vista RC1

"CuriousGeorge" wrote:
Because no nulls are referenced?
Hmmm. OK.

a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.

b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than that
its a pretty vanilla type.

As we know and event with no subscribers is actually a null-reference hence
the check for nullility before invoking the subscribed handlers.

If you in-line the delegate call in my original post you get something like
the following (compiled in Outlook Express)

public void RaiseEvent(Callback callback)
{
EventHandler temp = SomeEvent;

SomeEvent -= theOnlyRegisteredEventHandler
//SomeEvent is now null

if (temp != null)
{
temp(this, EventArgs.Empty);
}
}

The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:12*************@corp.supernews.com...
"CuriousGeorge" <***@***.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
Can someone explain why this code DOES NOT raise a null reference
exception?
Because no nulls are referenced?

If you have reason to believe that a null reference exception should
occur, then the least you could do is explain in your post:
a) why it is you want to execute code like this, and
b) why and where it is that you think a null reference exception would
occur

Pete


Oct 28 '06 #5
"Delegates are immutable; once created, the invocation list of a delegate
does not change."

Word. Thanks Mark, I hadn't seen that bit of doco. The thing is, I did skim
the (managed) rotor source for delegates and saw nothing that suggested
immutability in the implementation. Forgive my ignorance but where in the IL
can I see this? (is it a type decorator)

"Why not just ask the question you want to ask :-)"

Quite simply, I don't have the expertise to express myself very well.

Case in point, immutability, I see it, I hear it, it is said by the oracle,
MSDN, however, the upshot is (to all intents and purposes) that the
assignment operator behaves like it is overloaded such that it works like a
value type. I have taken this as gospel for years with the System.String
class but now I see it here and it is making my head spin!!

Words fail me.

Please help :)
"Mark R. Dawson" <Ma*********@discussions.microsoft.comwrote in message
news:A1**********************************@microsof t.com...
Hi,
>a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.

I don't see anything particularly thread safe about your code, are you
talking about checking for null that makes this thread safe? It is safe
for
a single thread but once you have multiple threads the really only safe
way
is to make sure you have locks in place around adding/removing delegates
to
your event and the invocation of that event i.e. the following is an
example
of how two threads accessing the same event can cause a null reference
exception:

using System.Threading;

namespace CSharpConsole
{
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.Run();
}
}

class TestClass
{
private delegate void MyEventHandler();
private event MyEventHandler MyEvent;

public TestClass()
{
}

public void Run()
{
Thread threadA = new Thread(new
ThreadStart(ThreadADoSomething));

//Add listener to the event
MyEvent += new MyEventHandler(DoSomething);

if (MyEvent != null)
{
//got in here, let the other thread run and wait until it
//completes
threadA.Start();
threadA.Join();

//whoops now this is null
MyEvent();
}
}

void ThreadADoSomething()
{
//removes the only listener
MyEvent -= new MyEventHandler(DoSomething);
}

void DoSomething()
{
}
}
}
>b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than
that
its a pretty vanilla type.

There is a little bit more to this type, hence your posting :-) If you
look
at the documentation for the delegate type you will see: "Delegates are
immutable; once created, the invocation list of a delegate does not
change."
Hence the reason why when you assign you event (which is really just
syntactic sugar around delgates) to your other delegate type really you
have
just made a new copy of that delegate. The contents of the
multicastdelegates invocation list inside the temp variable will therefore
not change when you update the other multicastdelegate through the
SomeEvent
enty point.

>The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.

Why not just ask the question you want to ask :-)
--
http://www.markdawson.org
Posted from Windows Vista RC1

"CuriousGeorge" wrote:
Because no nulls are referenced?
Hmmm. OK.

a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.

b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than
that
its a pretty vanilla type.

As we know and event with no subscribers is actually a null-reference
hence
the check for nullility before invoking the subscribed handlers.

If you in-line the delegate call in my original post you get something
like
the following (compiled in Outlook Express)

public void RaiseEvent(Callback callback)
{
EventHandler temp = SomeEvent;

SomeEvent -= theOnlyRegisteredEventHandler
//SomeEvent is now null

if (temp != null)
{
temp(this, EventArgs.Empty);
}
}

The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:12*************@corp.supernews.com...
"CuriousGeorge" <***@***.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
Can someone explain why this code DOES NOT raise a null reference
exception?

Because no nulls are referenced?

If you have reason to believe that a null reference exception should
occur, then the least you could do is explain in your post:
a) why it is you want to execute code like this, and
b) why and where it is that you think a null reference exception
would
occur

Pete



Oct 28 '06 #6
"CuriousGeorge" <***@***.comwrote in message
news:%2******************@TK2MSFTNGP02.phx.gbl...
a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.
I disagree. As Mark points out, there's nothing thread-safe about the code
that you posted.
[...]
The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
Well, hopefully at this point, given the responses you've seen, it should be
clear to you that it was NOT "pretty self-explanatory".

On the bright side, it looks like you did finally get the answer to your
question. :)

Pete
Oct 28 '06 #7
CuriousGeorge <***@***.comwrote:
Because no nulls are referenced?
Hmmm. OK.

a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.
It's not, actually. Your code isn't genuinely thread-safe. See
http://www.pobox.com/~skeet/csharp/t...ckchoice.shtml for a
genuinely thread-safe pattern.
b) Events are basically delegates
No they're not. Events are pairs of methods. Field-like events declare
both an event and a delegate.
System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than that
its a pretty vanilla type.
Actually, it *doesn't* overload += and -=. Instead, the C# compiler
calls Delegate.Combine or Delegate.Remove, both of which are static
methods which can take null arguments.

See http://www.pobox.com/~skeet/csharp/events.html for more
information.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Oct 29 '06 #8
Peter Duniho <Np*********@NnOwSlPiAnMk.comwrote:
"CuriousGeorge" <***@***.comwrote in message
news:%2******************@TK2MSFTNGP02.phx.gbl...
a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.

I disagree. As Mark points out, there's nothing thread-safe about the code
that you posted.
In fairness to the OP, I wouldn't go that far. It's not *quite* thread-
safe, but it's safer than the normal pattern of:

if (EventName != null)
{
EventName (...);
}

where "EventName" is a field-like event.

The problem with the above is that another thread could change the
value of myEventName to null between the check and the call. The OP's
code tries to avoid that by using a local variable. Now, there's some
debate as to the exact guarantees of behaviour of local variables in
the memory model, but it's at least a reasonable start. However, the
lack of locking and volatility means that if one thread adds a load of
event handlers, they may never be noticed by the thread raising the
event, which isn't generally what's wanted.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Oct 29 '06 #9
Jon, your arachsys stuff is, quite simply, GOLD

"Jon Skeet [C# MVP]" <sk***@pobox.comwrote in message
news:MP************************@msnews.microsoft.c om...
CuriousGeorge <***@***.comwrote:
Because no nulls are referenced?
Hmmm. OK.

a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.

It's not, actually. Your code isn't genuinely thread-safe. See
http://www.pobox.com/~skeet/csharp/t...ckchoice.shtml for a
genuinely thread-safe pattern.
>b) Events are basically delegates

No they're not. Events are pairs of methods. Field-like events declare
both an event and a delegate.
>System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than
that
its a pretty vanilla type.

Actually, it *doesn't* overload += and -=. Instead, the C# compiler
calls Delegate.Combine or Delegate.Remove, both of which are static
methods which can take null arguments.

See http://www.pobox.com/~skeet/csharp/events.html for more
information.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

Oct 29 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: serge calderara | last post by:
Dear all, I have a class wich is raising events as normally it should do. having a form in the same assembly wich is catching those events works fne. Raise events gets catch normaly within the...
6
by: Dan | last post by:
I've created a pocketpc app which has a startup form containing a listview. The form creates an object which in turn creates a System.Threading.Timer. It keeps track of the Timer state using a...
4
by: rawCoder | last post by:
Hi all, How Can You Raise Events Asynchronously ? Now for the details ... I want to do inter modular communication using events in such a way that the contributing modules need not...
7
by: cider123 | last post by:
I'm coding a project using the following article as reference: http://www.codeproject.com/csharp/DynamicPluginManager.asp In this type of project, plugins are loaded dynamically into a Plugin...
0
by: Greg Park | last post by:
I have many user controls loading into a web page using Page.LoadControl However, I'm unable to figure out how to raise an event when a button is click or a check box is checked. I can have...
0
by: Joe Campbell | last post by:
I am encountering a problem raising WMI events from an asp.net application. The error received (as captured in the event log) is as follows: System.Runtime.InteropServices.COMException...
4
by: Dave A | last post by:
I am developing a somewhat complex component at the moment and coincidently I am also reading the Framework Design Guidelines book. After reading the section about event raising I have re-written...
2
by: Gman | last post by:
Hi, I have created a usercontrol, a grid control essentially. Within it I have a class: clsGridRecord. I have coded the events such that when a user clicks on the grid, say, the events occur on...
0
by: Apu Nahasapeemapetilon | last post by:
Suggestions on cross-posting this issue would be appreciated. I've got a C# .NET DLL (CLR v1.1) that raises events into its container. When the container is a .NET application, raising the...
7
by: Christian Cambier | last post by:
Hi, I have a textbox in a web user control. I then add the usercontrol to a web form. I also add a label in the web form. Now, when I press a key in the textbox, i want to display some text...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.