473,326 Members | 2,182 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,326 software developers and data experts.

Delegate Invocation List contains COPIES of objects, NOT reference

N8
I am trying to get an exception to occur and consequently found that when
adding a target method to a delegates invocation list, a copy of that object
is added instead of a reference to the object.

Here's what I'm trying to do... I am iterating through the invocation list
invoking each delegate manually. I want to eventually try to invoke a
delegate to an object that has been destroyed. I'm essentially looking to get
the exception "object not set to an instance of an object" or some kind of
exception.

I've created two classes to test with, one class has a delegate as follows:

public class classContainsDelegate{
public delegate void takesOneString(string message);
public takesOneString myStringEvent;

public void raiseEvent(string message){
if(myStringEvent != null){
foreach(takesOneString d in myStringEvent.GetInvocationList()){
d(message);
}//foreach
}//if
}//raiseevent
}//class
I have another class that is going to simply display the message, when
called by the above delegate:

public class classBeingCalledBack(string key){
private string key = "";

public classBeingCalledBack(string theKey){
key = theKey;
}//new method

public string Key{
get{return key;}
}//key property

public void theCallback(string message){
Console.WriteLine("theCallback received '{0}' by '{1}', message, key);
}//the callback
}//class
My test routine starts out like this:

classContainingDelegate d1 = new classContainingDelegate();
classBeingCalledBack o1 = new classBeingCalledBack("first instance");
classBeingCalledBack o2 = new classBeingCalledBack("second instance");

d1.myStringEvent += new
classContainingDelegate.takesOneString(o1.theCallB ack);
d1.myStringEvent += new
classContainingDelegate.takesOneString(o2.theCallB ack);

d1.raiseEvent("message #1");

When I run this test, the 2 callbacks are made to both objects and I see the
messages being displayed that the callbacks happened for objects keyed "first
instance" and "second instance".

Now I want to kill the "first instance" object altogether. I want to cause
an exception when the delegate goes to make a callback to an object that
shouldn't exist anymore. So I then add the following lines to my test routine:

o1 = null;
d1.raiseEvent("message #2");

When doing this, I still get both callbacks still. No exceptions being thrown!

Now, even if I go and change o1 like:
o1 = new classBeingCalledBack("first instance - version 2");

When the delegate is called for "o1", I would expect to see a message that
the callback occurred for "first instance - version 2", but instead I see
"first instance" which should have been overwritten.

I have tried forcing a garbage collection, no difference.

I have tried creating an Event instead of using a delegate (yeah I know its
the same thing, but the rules slightly differ between the two) and no
difference.

Anybody have any ideas? What am I doing wrong or not getting here?

Thanks in advance.
Nov 16 '05 #1
3 2304
N8,

The reason this happens is that when you create a delegate, the delegate
itself holds a reference to the object that the method is on. This way,
when you set the original reference to null, and do a GC, the object still
lives, because you are holding the delegate, which holds the object.

A copy of the object is not made, but rather, the original is just kept
alive because you are holding a reference (indirectly through the delegate)
to it.

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"N8" <N8@discussions.microsoft.com> wrote in message
news:C9**********************************@microsof t.com...
I am trying to get an exception to occur and consequently found that when
adding a target method to a delegates invocation list, a copy of that
object
is added instead of a reference to the object.

Here's what I'm trying to do... I am iterating through the invocation list
invoking each delegate manually. I want to eventually try to invoke a
delegate to an object that has been destroyed. I'm essentially looking to
get
the exception "object not set to an instance of an object" or some kind of
exception.

I've created two classes to test with, one class has a delegate as
follows:

public class classContainsDelegate{
public delegate void takesOneString(string message);
public takesOneString myStringEvent;

public void raiseEvent(string message){
if(myStringEvent != null){
foreach(takesOneString d in myStringEvent.GetInvocationList()){
d(message);
}//foreach
}//if
}//raiseevent
}//class
I have another class that is going to simply display the message, when
called by the above delegate:

public class classBeingCalledBack(string key){
private string key = "";

public classBeingCalledBack(string theKey){
key = theKey;
}//new method

public string Key{
get{return key;}
}//key property

public void theCallback(string message){
Console.WriteLine("theCallback received '{0}' by '{1}', message, key);
}//the callback
}//class
My test routine starts out like this:

classContainingDelegate d1 = new classContainingDelegate();
classBeingCalledBack o1 = new classBeingCalledBack("first instance");
classBeingCalledBack o2 = new classBeingCalledBack("second instance");

d1.myStringEvent += new
classContainingDelegate.takesOneString(o1.theCallB ack);
d1.myStringEvent += new
classContainingDelegate.takesOneString(o2.theCallB ack);

d1.raiseEvent("message #1");

When I run this test, the 2 callbacks are made to both objects and I see
the
messages being displayed that the callbacks happened for objects keyed
"first
instance" and "second instance".

Now I want to kill the "first instance" object altogether. I want to cause
an exception when the delegate goes to make a callback to an object that
shouldn't exist anymore. So I then add the following lines to my test
routine:

o1 = null;
d1.raiseEvent("message #2");

When doing this, I still get both callbacks still. No exceptions being
thrown!

Now, even if I go and change o1 like:
o1 = new classBeingCalledBack("first instance - version 2");

When the delegate is called for "o1", I would expect to see a message
that
the callback occurred for "first instance - version 2", but instead I see
"first instance" which should have been overwritten.

I have tried forcing a garbage collection, no difference.

I have tried creating an Event instead of using a delegate (yeah I know
its
the same thing, but the rules slightly differ between the two) and no
difference.

Anybody have any ideas? What am I doing wrong or not getting here?

Thanks in advance.

Nov 16 '05 #2
N8
Thanks Nicholas,

You are right! I completely forgot the rules there when doing this test. (I
blame my xmas vacation - lol).

Thanks again.
Nov 16 '05 #3
Nicholas Paldino [.NET/C# MVP] wrote:
N8,

The reason this happens is that when you create a delegate, the
delegate itself holds a reference to the object that the method is
on. This way, when you set the original reference to null, and do a
GC, the object still lives, because you are holding the delegate,
which holds the object.
A copy of the object is not made, but rather, the original is just
kept alive because you are holding a reference (indirectly through
the delegate) to it.


Indeed, But of course the delegate is serializable, if the objects that are
reference are also serializable. Which gives you the odd situation that you
can serialize a delegate, shutdown the app, re start the app, deserialize
the delegate and invoke it. Resurection of the objects!

Richard
--
www.richardgrimes.com
my email ev******@zicf.bet is encrypted with ROT13 (www.rot13.org)
Nov 16 '05 #4

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

Similar topics

4
by: Jon Davis | last post by:
If two delegates are created that point to the exact same method, and an event is assigned both delegates, ... myObj.MyEvent += new EventHandler(MyHandler); myObj.MyEvent += new...
6
by: Sharon | last post by:
How to catch an asynchronous delegate invocation exception? The code: --------------------------------------- String message = “my message”; foreach( MyDelegate handler in...
2
by: Ed A | last post by:
Hi all: My class has one event that gets fired on a timer, typically only one function consumes it on the receiving end. // Source Class public delegate void DataHandler(ArrayList aList);...
0
by: Nate | last post by:
I am creating an application that is quite complex. There will be several dozen objects, most of which have delegates defined. At runtime, there will be several hundred instances of some objects...
3
by: Jeff S | last post by:
Please consider this sample code: It registers a delegate with an event. p1.FirstNameChanged += new Person.NameChanged(p1_FirstNameChanged); Now the following code removes the delegate:...
1
by: Quimbly | last post by:
I'm having some problems comparing delegates. In all sample projects I create, I can't get the problem to occur, but there is definitely a problem with my production code. I can't give all the...
5
by: Larry Smith | last post by:
Hi there, Given a delegate that points to a non-static member function, is there a cleaner way to change the object instance it's called on other than invoking "Delegate.CreateDelegate()" (and...
11
by: matsi.inc | last post by:
I am looking to make something like a delegate that i can use in my projects but am having a hard time getting started. The behavior I am most interested in is how a delegate changes it's Invoke...
6
by: damiensawyer | last post by:
Hi, Can someone please explain to me something about delegates? My understanding is as follows. A delegate is basically an object that can hold a reference to a "method" somewhere. That is,...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, youll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shllpp 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
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...

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.