Newbie Delegate Question

D

damiensawyer

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, it's
essentially a pointer to a piece of code somewhere else in memory.

It therefore (to me anyway) makes sense to define delegates with their
signatures and be able to use those signatures at different points in
code. That way, if the signatures of various methods are defined by
the delegate, you 'know' that you can store references to those
methods in your delegates.

My question is, is there a way to define a method, referring to a
delegate to source it's parameter list?

I hope this makes sense. Please feel free to pull me up if I'm missing
the point completely.

Thanks in advance.


Damien



--------- working sample --------

<%@ Page Language="C#" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">

public delegate void WriteLogHandler(WriteLogEventHandler
args); // note - deliberately left out "object Sender" parameter to
keep demo simple.
public class WriteLogEventHandler : EventArgs
{
private string message;
public WriteLogEventHandler(string Message)
{
message = Message;
}
public string Message
{
get{return message;}
}
}

public class Person
{
public event WriteLogHandler WriteLog;

public void FireAnEvent()
{
if (WriteLog != null) WriteLog(new
WriteLogEventHandler("Hello Delegate World"));
}
}

protected void Page_Load(object sender, EventArgs e)
{
Person SamplePerson = new Person();
SamplePerson.WriteLog += new
WriteLogHandler(SamplePerson_WriteLog);
SamplePerson.FireAnEvent();
}

/// The question I have is, can I pass in some reference to
"WriteLogHandler"
/// as the argument to the below method? By doing it the way it is
below, I have to keep the delegate and
/// this signiture (and however many others) in sync.
void SamplePerson_WriteLog(WriteLogEventHandler args)
{
this.Form.InnerHtml += args.Message + "<br/>";
}

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h3>Delegate Primer</h3>
</div>
</form>
</body>
</html>
 
A

.\\\\axxx

If I understand what you are asking, then no, you cant do it.
Are you saying you want to change the signature in one place (the
delegate definition) and to have that change update all methods that
are used with that delegate to have the same signature?

I can (sort of ) see where you are coming from - but if the signature
changes, one would think that (usually) you would need to change the
content of any methods whose signature has changed, anyway (.e.g if
your WriteLogEventHandler needed an extra parameter to specify the
colour of the output (I know it's not a good example, but it's late)
then you would have to change not only the signature of the method,
but also the content - and one method's parameter name may sensibly be
"debugColour" while another may be "errorColour" (again, crap examples
but I hope you see where I am coming from!).

I think if delegates more of being references to particualr methods -
not just to method signatures. Sure, you can have a generic delegate
that would 'point' to any method with a particular signature - but
then you have the issue when only a subset of the methods you
reference change their signature.

So if you think of the delegate as being a reference to some
functionalilty, rather than a particular signature, you may end up
with more delegates, but I think you may find it a more robust
solution in the long run.

Alternately you could define a delegate which defines collection of
objects as its parameter, and define all your 'delegatable methods' in
the same manner - then the signature would never change- you just add
another object to the collection... ;)
 
D

damiensawyer

If I understand what you are asking, then no, you cant do it.

Bummer.
Are you saying you want to change the signature in one place (the
delegate definition)  and to have that change update all methods that
are used with that delegate to have the same signature?
Exactly!

I can (sort of ) see where you are coming from - but if the signature
changes, one would think that (usually) you would need to change the
content of any methods whose signature has changed, anyway

hmmm... good point.
I think if (of?) delegates more of being references to particualr methods -
not just to method signatures.

Sure. However this comes back to my original point. If you had said "I
think of a delegate more of being references to a particular
method" (as in, one single method) then I'd understand completely.

However, if a (single) delegate is to hold references to "multiple
methods" (hence the point of having a delegate 'variable' in the first
place) - then it would seem to me to syntactically make sense to be
able to define/modify all of those methods in a combined way. See my
point? Either delegates are 'meant' to refer to single methods or
multiple. It would seem, by the ommission of the syntax construct I
was asking about, that the designers may have been thinking single (or
maybe have just considered such a construct 'syntactic sugar').


Sure, you can have a generic delegate
that would 'point' to any method with a particular signature - but
then you have the issue when only a subset of the methods you
reference change their signature.

Good point. However is that issue any different under the current
design?

So if you think of the delegate as being a reference to some
functionalilty, rather than a particular signature, you may end up
with more delegates, but I think you may find it a more robust
solution in the long run.

I'm not 100% sure what you're getting at here... I'll have to mull
this one over.
Alternately you could define a delegate which defines collection of
objects as its parameter, and define all your 'delegatable methods' in
the same manner - then the signature would never change- you just add
another object to the collection... ;)

*grin*.


Thanks for your help :)
 
A

.\\\\axxx

What I was getting at (sorry - I'm using google groups and I'm not
sure how to answer in-line) is that you seem to be thinking of
delegates and their associated methods in terms of their signatures,
rather than what functions they perform.

public void ShowMessageOnForm(string message){...}
and
public void DeleteFile(string path){...} have the same signature, and
therefore could have the same delegate - but I would always use a
different delegate for each.

Sure that's an extreme example - but I tend to think that being
specific with a delegate reduces problems down the line when one of
the methods may require a signature change while the other does not.

So I have 'Form change Event' delegates (note plural) which are used
to refer to all events on all forms in my appliciation, each of which
implement an interface specifying the event handler signature, but
each of them is defined independently because the information required
_may_ change independently of all others (e.g. a change in the
customer maintenance form may require additional information to be
processed by the event handler, such as an email address to send an
email to, while a change to other forms may simply need to inform that
a change of some description has been made).

Now with many forms, this is a large number of identically signatured
delegates - but the maintenance is simple if a single signature
changes - and if multiple signatures change thn I did some poor design
in the first place and deserve the angst of changing them all :)

In thinking about this, I can't see a greason why what you are asking
for would not be possible as a pre-compilation event.

So you'd define your signature

#preprocess myDelegateSig "(sting param1, string param2)

and your delegate

public delegate <myDelegateSig> MyEventHandler;

and your method(s)

public <myDelegateSig> myMethod
{
MessageBox.Show(param1 + param2);
}

if you fogive my made-up syntax - but you probably get the idea...

So, in principle it could be possible - but I'm not sure that it
really helps.

Cheers
 
J

Jon Skeet [C# MVP]

Can someone please explain to me something about delegates?

You might want to read
http://pobox.com/~skeet/csharp/events.html
My understanding is as follows. A delegate is basically an object that
can hold a reference to a "method" somewhere. That is, it's
essentially a pointer to a piece of code somewhere else in memory.

Sort of. Actually all delegates are (potentially) multicast in .NET -
so it's a reference to a list of methods. Each method also has a
target associated with it - essentially which object to call the
method on. (This is null for static methods.)
It therefore (to me anyway) makes sense to define delegates with their
signatures and be able to use those signatures at different points in
code. That way, if the signatures of various methods are defined by
the delegate, you 'know' that you can store references to those
methods in your delegates.

I personally tend to use the new Func and Action delegate types
in .NET 3.5 - they mean I don't need to sprinkle my code with delegate
type declarations.
My question is, is there a way to define a method, referring to a
delegate to source it's parameter list?

No, I'm afraid not.
--------- working sample --------

Console applications are generally a lot better for samples than
ASP.NET applications. With a full console app, I can just copy, paste
and compile straight from the command line. No need to create an
ASP.NET project, bring up a web server etc. However:
/// The question I have is, can I pass in some reference to
"WriteLogHandler"
/// as the argument to the below method? By doing it the way it is
below, I have to keep the delegate and
/// this signiture (and however many others) in sync.
void SamplePerson_WriteLog(WriteLogEventHandler args)

Have you actually had problems with this in practice? How often do you
change delegate signatures? When you change a delegate signature,
you'll probably need to change all the implementing methods anyway, or
at least check that they're still valid with all the new parameters.

Jon
 
D

damiensawyer

Thanks heaps for that guys, I think it's clearing up.

[Quoting .\axxx]
In that case, it seems to me that you might as well just define a single
type that is _the_ argument to any method that would use that
"signature". Then if you change the type itself, the signature of the
method is effectively changed.

In my original post, I guess that's effectively what
WriteLogEventHandler is?

[Quoting Peter]
I see your point, but only in the sense that it relies on a basic
misunderstanding of what a delegate is.

Yep - I think that you're right.
On top of all that, keep in mind that when you set a delegate to a value,
you're not necessarily just referencing the method. For instance methods,
you are referencing the method _and_ the instance that will be used to
invoke the method.

Ok.... that's definitely along different lines than what I've been
thinking... but starting to make sense. By adding 'instances' to each
method, it sort of adds another whole dimension to the puzzle. I think
now that I can start to imagine better what delegates should be
doing...
But the value stored in a delegate is no more the signature than
the value stored in something declared "int" is itself a description of an
"int"

Great descrption!

[Quoting Jon]
I personally tend to use the new Func and Action delegate types
in .NET 3.5 - they mean I don't need to sprinkle my code with delegate
type declarations.

Not heard of these before. I'll look them up.
No, I'm afraid not.

I think that I have a better understanding of their purpose now which
is great.


Thanks guys for all your help :)




DS
 

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