469,286 Members | 2,521 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,286 developers. It's quick & easy.

Delegates are useful, and here is why (sample program)

They usually don't teach you in most textbooks I've seen that
delegates can be used to call class methods from classes that are
'unaware' of the delegate, so long as the class has the same signature
for the method (i.e., as below, int Square (int)).

Here is an example to show that feature. Note class "UnAwareClass"
has its methods Square and Cuber called by a class DelegateClass.
This is because these methods in UnAwareClass have the same signature
and so they can be called by DelegateClass, without the keyword
'delegate' ever appearing in UnAwareClass.

Note the keyword 'static' has to be used as below, even though
UnAwareClass itself is not static, though there is a way to use
delegates with non-static functions (however I don't see the need to
do so).

Pretty cool if you ask me--like a functor in C++.

RL

//Delegate model showing how another class (ďUnAwareClassĒ) does not
even have to be aware of the delegate and still be called and
employed.
///

///////
// OUTPUT (takes the square of a number, here 11, and the cube, to
give 121 and 1331)

...now for external use of delegates from two classes...
Square 11 is: 121
!Cube 11 is: 1331
Press any key to continue . . .
///////

using System;
using System.Collections.Generic;
using System.Text;

namespace EventDelegates
{
class Program
{
static void Main(string[] args)
{

UnAwareClass myUnAwareClass = new UnAwareClass();

// now to access delegate from another class

Console.WriteLine("...now for external use of delegates from two
classes...");

DelegateClass.PublicHigherPower2 sQr = new
DelegateClass.PublicHigherPower2(UnAwareClass.Squa re); //!!! Note: how
called: UnAwareClass.Square

DelegateClass myDelegateClass = new DelegateClass(); //
apparently no ill effects if follows rather than preceeds previous
line

int ji2 = myDelegateClass.DoOp(sQr, 11);

Console.WriteLine("Square 11 is: {0}", ji2);

DelegateClass.PublicHigherPower2 Cub2 = new
DelegateClass.PublicHigherPower2(UnAwareClass.Cube r);

//!!! note: how called: UnAwareClass.Cuber

ji2 = myDelegateClass.DoOp(Cub2, 11);

Console.WriteLine(" !Cube 11 is: {0}", ji2);

// !!!Note significance: 'delegate' keyword NEVER APPEARS in class
UnAwareClass (!)

}
}
}
////////////
using System;
using System.Collections.Generic;
using System.Text;

namespace EventDelegates
{
class UnAwareClass
{

//!! in this version, 'delegate' keyword does not appear in
this class (UnAwareClass) but only DelegateClass class

int[] values;
int i;
public UnAwareClass()
{
values = new int[] { 1, 2, 3 }; //not used
i = 22333; //not used
}
public static int Square(int x)
{
return x * x;
}
public static int Cuber(int y)
{
return y * y * y;
}
}

class DelegateClass
{
public delegate int PublicHigherPower2(int x); //delegate to
be used externally (keyword delegate must of course be declared here)

int j;
public DelegateClass()
{
j = 0;
}

public int DoOp(PublicHigherPower2 ar, int x) //note format
{
return ar(x);
}
}

}
Jul 13 '08 #1
69 5149
Was there a question? (which is kinda what this group is aimed at...)

But I'm not sure that this is a massively useful example of
delegates... in particular, Main could simply use the actual method
directly, rather than using delegates. Delegates become useful when
the code that invokes them cannot possibly know about the actual
methods (such as List<T>.Find). I'm counting "Main" as the calling
code since DelegateClass/DoOp don't actually add anything - Main could
just as easily call sQr(11) and Cub2(11).

Re delegate not appearing in UnAwareClass, I'm not sure that should
surprise us? By comparison to C++, the targeteted method wouldn't know
about a void-pointer, either. And theer is a lot of unused stuff...
(i, j, values, 2 constructors) - it just adds confusion.

Note that .NET 3.5 adds some re-usable generic delegates such as
Func<int,intthat can be used in place of declaring your own.

Just some pointers... [no pun intended]

Marc
Jul 13 '08 #2
On Jul 13, 12:56*am, Marc Gravell <marc.grav...@gmail.comwrote:
Was there a question? (which is kinda what this group is aimed at...)
No, it was a comment.
>
But I'm not sure that this is a massively useful example of
delegates... in particular, Main could simply use the actual method
directly, rather than using delegates.
Please. You realize that delegates are not even necessary, ever, and
you can do everything a delegate can do (even an Event delegate that
publishes and is subscribed to) with simple calls to methods. More
clumsy and a code maintenance nightmare, but it works. Delegates are
just a programming paradigm. Some say delegates and events were
introduced in the CLI langauges of C++ and C# by Microsoft to make
them more compatible to Visual Basic (I read that once).
>
Re delegate not appearing in UnAwareClass, I'm not sure that should
surprise us?
Well it surprised me, since all the examples in my numerous textbooks
were contra.
Note that .NET 3.5 adds some re-usable generic delegates such as
Func<int,intthat can be used in place of declaring your own.
Don't see how this is relevant--generic templates are well known and
another subject.

Thanks for replying. Happy coding.

RL
Jul 13 '08 #3
On Jul 13, 1:16*pm, raylopez99 <raylope...@yahoo.comwrote:
Please. *You realize that delegates are not even necessary, ever, and
you can do everything a delegate can do (even an Event delegate that
publishes and is subscribed to) with simple calls to methods. *More
clumsy and a code maintenance nightmare, but it works. *Delegates are
just a programming paradigm. *Some say delegates and events were
introduced in the CLI langauges of C++ and C# by Microsoft to make
them more compatible to Visual Basic (I read that once).
Delegates are just function pointers closed over the first argument of
the function. Events are just syntactic sugar for the Observer
pattern. There is no "paradigm" to them, and they have little to do
with VB6, either: VB6 had events which were vaguely similar
syntactically, but not delegates. A better example would be Delphi -
it had "function of object" type which was almost equivalent to C# non-
multicast delegates.
Jul 13 '08 #4
On Jul 13, 3:54*am, Pavel Minaev <int...@gmail.comwrote:
Delegates are just function pointers closed over the first argument of
the function. Events are just syntactic sugar for the Observer
pattern. There is no "paradigm" to them, and they have little to do
with VB6, either: VB6 had events which were vaguely similar
syntactically, but not delegates. A better example would be Delphi -
it had "function of object" type which was almost equivalent to C# non-
multicast delegates.
Thanks for that insight. I stand corrected and after reading
Wikipedia's entry, I understand what syntactic sugar means.

RL

Jul 13 '08 #5
Here is an updated version of this program I worked on today, that
shows 'inline or anonymous delegates' (at least for version 2.0, since
I don't have version 3.0 of C#), multicasting (and the syntax for it),
traversing an array of delegates. If anybody cares to comment, please
post how in version 3.0 you would declare a (anonymous) delegate
"inline" and 'inside' a class method (see comment below: "; //cannot
declare here! compiler errror, must be done outside of class method--
one disadvantage apparently of version 2.0" and, "//NOT ALLOWED! must
be outside of...")

RL

// start of output

....now for external use of delegates from two classes...
Square inside method:121
Square 11 is: 121
Cube inside method:1331
!Cube 11 is: 1331
z:123
number returnINT 123 is: 123
z:345
number returnINT 345 is: 345
..................
now try multicasting delegates that accept a single parameter
the number of delegates in this list is: 5
Square inside method:12321
Cube inside method:1367631
z:111
Cube inside method:1367631
z:111
....now remove a chained delegate, say sQr, from the invocation list...
the number of delegates in this list is: 4
.............________...........
demonstrate that parameter returned for val is an integer, as
expected;
One advantage of delegates over Events is that a delegate can return a
value dir
ectly,and doesn't have to be void
.............________...........
Cube inside method:1367631
the integer returned in the multicast delegate is: 1367631
z:111
the integer returned in the multicast delegate is: 111
Cube inside method:1367631
the integer returned in the multicast delegate is: 1367631
z:111
the integer returned in the multicast delegate is: 111
New Style Delegate: fourth power of ten is 10k: 10000
Press any key to continue . . .

// end of output

using System;
using System.Collections.Generic;
using System.Text;

namespace del071308
{

class Program
{
public delegate int NewStyleDelegate(int i); //used later on
below for 'new style' static method delegate without need for a class
instantiation, but done inline

static void Main(string[] args)
{

UnAwareClass myUnAwareClass = new UnAwareClass();
// now to access delegate from another class

Console.WriteLine("...now for external use of delegates
from two classes...");

DelegateClass.PublicHigherPower2 sQr = new
DelegateClass.PublicHigherPower2(UnAwareClass.Squa re); //!!! Note: how
called: UnAwareClass.Square

DelegateClass myDelegateClass = new DelegateClass();
// apparently no ill effects if follows rather than
preceeds previous line

int ji2 = myDelegateClass.DoOp(sQr, 11);

Console.WriteLine("Square 11 is: {0}", ji2);

DelegateClass.PublicHigherPower2 Cub2;
Cub2 = new
DelegateClass.PublicHigherPower2(UnAwareClass.Cube r); //long way - 2
lines instead of one

DelegateClass.PublicHigherPower2 RetINT;
RetINT = new
DelegateClass.PublicHigherPower2(myUnAwareClass.re turnINT);

DelegateClass.PublicHigherPower2 RetINT2 = new
DelegateClass.PublicHigherPower2(myUnAwareClass.re turnINT); //note
format equivalent
//!!! note: how called: UnAwareClass.Cuber

ji2 = myDelegateClass.DoOp(Cub2, 11);

Console.WriteLine(" !Cube 11 is: {0}", ji2);

// !!!Note significance: 'delegate' keyword NEVER APPEARS
in class UnAwareClass (!)

int uiu = 0;
uiu = myDelegateClass.DoOp(RetINT, 123);
Console.WriteLine("number returnINT 123 is: {0}", uiu);

int iui;
iui = myDelegateClass.DoOp(RetINT2, 345);
Console.WriteLine("number returnINT 345 is: {0}", iui);
//now try multicasting, combining delegates. Note
multicasting is less flexible in a way since only one parameter can be
passed that is common to all delegates

Console.WriteLine(".................");

Console.WriteLine("now try multicasting delegates that
accept a single parameter");
DelegateClass.PublicHigherPower2 CombinedDelegates01;
CombinedDelegates01 = sQr + Cub2;
CombinedDelegates01 += RetINT;
//add another delegate, and instantiate at the same time
CombinedDelegates01 += new
DelegateClass.PublicHigherPower2(UnAwareClass.Cube r);
CombinedDelegates01 += RetINT2; //add yet another delegate

int delegateInvocationCount =
CombinedDelegates01.GetInvocationList().GetLength( 0);
Console.WriteLine("the number of delegates in this list
is: {0}", delegateInvocationCount);
// CombinedDelegates01.GetInvocationList(); // is An array
of delegates representing the invocation list of the current delegate
//easy way to traverse an array of unknown length, rather
than using GetLength property
(CombinedDelegates01.GetInvocationList().GetLength (0);) is to use
foreach:

foreach (DelegateClass.PublicHigherPower2 val in
CombinedDelegates01.GetInvocationList())
{
val.Invoke(111); //uses variable 111 as parameter
(req'd)

}
//now remove a chained delegate, say sQr, from the
invocation list
Console.WriteLine("...now remove a chained delegate, say
sQr, from the invocation list...");

CombinedDelegates01 -= sQr; //note format to remove
// run array of delegates again, and see that this
delegate now missing
delegateInvocationCount =
CombinedDelegates01.GetInvocationList().GetLength( 0);
Console.WriteLine("the number of delegates in this list
is: {0}", delegateInvocationCount);

// CombinedDelegates01.GetInvocationList(); // is An array
of delegates representing the invocation list of the current delegate

//easy way to traverse an array of unknown length, rather
than using GetLength property
(CombinedDelegates01.GetInvocationList().GetLength (0);) is:

foreach (DelegateClass.PublicHigherPower2 val in
CombinedDelegates01.GetInvocationList())
{
}

Console.WriteLine("............________........... ");
Console.WriteLine("demonstrate that parameter returned for
val is an integer, as expected;");
Console.WriteLine("One advantage of delegates over Events
is that a delegate can return a value directly,"
+ "and doesn't have to be void");
Console.WriteLine("............________........... ");

foreach (DelegateClass.PublicHigherPower2 val in
CombinedDelegates01.GetInvocationList())
{
// also demonstrate that parameter returned for val is
an integer, as expected

int j = val.Invoke(111); //uses variable 111 as
parameter (req'd)
Console.WriteLine("the integer returned in the
multicast delegate is: {0}", j);

}
// now demonstrate 'new style C#3.0' static method for
delegates (no need for a class, or, rather, done inline)

// public delegate int NewStyleDelegate (int i); //
cannot declare here! compiler errror, must be done outside of class
method--one disadvantage apparently of version 2.0

NewStyleDelegate FourthPower = delegate(int i)
{
return i * i * i * i;
};

int for4thPowerTen = FourthPower.Invoke(10);

Console.WriteLine("New Style Delegate: fourth power of ten
is 10k: {0}", for4thPowerTen);

// Console.WriteLine("now an inline new style anonymous
method delegate is shown for C# 3.0");

{ //start of local variable bracket

// delegate int NewStyleDelegate2(int i); //NOT
ALLOWED! must be outside of class method main(), apparently since this
compiler is Version 2.0 (C# 2005), not Ver. 3.0

} // end of local variable bracket

}
}
class UnAwareClass
{

//!! in this version, 'delegate' keyword does not appear in this class
(UnAwareClass) but only DelegateClass class
int[] values;
int i;
public UnAwareClass()
{
values = new int[] { 1, 2, 3 }; //not used
i = 1; //not used
}
public static int Square(int x)
{
int sq = x * x;
Console.WriteLine("Square inside method:{0}", sq);
return x * x;
}
public static int Cuber(int y)
{
int Cube = (int)Math.Pow((double)y, (double)3); // that
is, Cube = y * y * y;
Console.WriteLine("Cube inside method:{0}",Cube);
return Cube;
}

public int returnINT(int z) //non-static member function that
matches the delegate signature of: int Foo (int)
{
Console.WriteLine("z:{0}", z);
return z;
}
}

class DelegateClass
{
public delegate int PublicHigherPower2(int x); //delegate to
be used externally (keyword delegate must of course be declared here)

int j;
public DelegateClass()
{
j = 0;
}

public int DoOp(PublicHigherPower2 ar, int x) //note format
{
return ar(x);
}
}
}
////////////
Jul 13 '08 #6
On Jul 13, 4:40*pm, raylopez99 <raylope...@yahoo.comwrote:
Here is an updated version of this program I worked on today, that
shows 'inline or anonymous delegates' (at least for version 2.0, since
I don't have version 3.0 of C#), multicasting (and the syntax for it),
traversing an array of delegates. *If anybody cares to comment, please
post how in version 3.0 you would declare a (anonymous) delegate
"inline" and 'inside' a class method (see comment below: "; //cannot
declare here! compiler errror, must be done outside of class method--
one disadvantage apparently of version 2.0" and, "//NOT ALLOWED! must
be outside of...")
No, I don't believe that code would ever have worked. You can't
declare another type inside a method, which is what you were trying to
do.

If you believe it would have worked with the C# 1 compiler, please
post a short but complete program demonstrating that. I'll see if I
can find a machine with .NET 1.1 on to compile it with - but I don't
believe you'll find it's ever worked.

Be aware that there's a big difference between declaring a delegate
*type* and declaring a *variable* of a delegate type.

Jon
Jul 13 '08 #7
On Sun, 13 Jul 2008 08:40:09 -0700, raylopez99 <ra********@yahoo.com>
wrote:
Here is an updated version of this program I worked on today, that
shows 'inline or anonymous delegates' (at least for version 2.0, since
I don't have version 3.0 of C#), multicasting (and the syntax for it),
traversing an array of delegates. If anybody cares to comment, please
post how in version 3.0 you would declare a (anonymous) delegate
"inline" and 'inside' a class method (see comment below: "; //cannot
declare here! compiler errror, must be done outside of class method--
one disadvantage apparently of version 2.0" and, "//NOT ALLOWED! must
be outside of...")
You are confusing the concept of a delegate _type_ with that of a delegate
_instance_. You are not allowed to declare types within a method body,
and that includes delegate types. The compiler version isn't the issue
here; it's that you don't fully understand delegates.

As for specific comments regarding your example, I'll start by pointing
out that MSDN has a MUCH MUCH better article introducing delegate types:
http://msdn.microsoft.com/en-us/libr...59(VS.71).aspx

It's from an earlier version of C# so it's missing some specific language
features, but it does so much of a better job of describing how and why to
use delegates, that's not important. And the newer features are described
in more recent articles, again in a much clearer way.

Here are a handful of things that come to mind with respect to your
program:

-- Creating your own delegate types is pointless. Just use Func<int,
intinstead

-- If you decide you must create your own delegate type, give it a
useful name. You named "DelegateClass.PublicHigherPower2" in a way that
implies a particular implementation for the delegate: taking the parameter
to the power of two. But of course, the actual delegate can do anything
that receives an int and returns an int (you even demonstrate that in your
code).

-- If you're going to try to write code examples for other people to
use, you need to pick a naming convention and stick with it. Using camel
case for some variable names, and then Pascal naming for others is just
going to distract the reader and make it difficult to see what the actual
point of the example is.

-- Don't name a variable with the word "class" (as in
"myDelegateClass") unless that variable is actually going to reference an
instance of an actual _class_ (that is, something that inherits Type and
is an actual class type).

-- Don't write comments in broken or abbreviated English. Again, if
this is for someone else to read, you need to make it readable. Comments
like "!!! note: how called: UnAwareClass.Cuber" are not descriptive or
informative. What is it that you really want the reader to note? In what
way is how "UnAwareClass.Cuber" called interesting? That information
needs to be in the comment; you can't just assume that the reader will
figure it out.

-- The comment "apparently no ill effects if follows rather than
preceeds previous line" makes no sense whatsoever. Why _would_ there be
any "ill effects" from reordering the lines of code being described?

-- The comment "!!!Note significance: 'delegate' keyword NEVER
APPEARS in class UnAwareClass (!)" also makes no sense. Why would the
"delegate" keyword have to appear in a class that doesn't use any
delegates? I might as well add comments that also say "!!!Note
significance: 'switch' keyword NEVER APPEARS..." and "!!!Note
significance: 'foreach' keyword NEVER APPEARS..." (to name a couple of
other keywords that don't appear in that class).

-- The multicast examples are just silly. They fail to demonstrate
the real use of multicast delegates, which is to take advantage of the
built-in traversal of the invocation list. If all you're going to do when
traversing the list is to call each delegate instance individually, then
just call the original multicast delegate directly. Your second multicast
example doesn't even call anything, so it's even more pointless.

-- I find it inconsistent and pointless to use the Math.Pow() method
for your cube function, considering you just explicitly multiply for
squaring and the fourth power. The explicit multiplication is more
readable and in any case, if you're writing a code sample, stick to one
thing. At the very least, pick one or the other approach.

-- For that matter, the comments about "foreach" are also
superfluous. A code sample should demonstrate one thing and demonstrate
it well. If you want to use "foreach", that's fine, but don't waste time
trying to teach that. It's not the point of the code sample and it just
obfuscates the main point of the sample. Likewise the use of the
Math.Pow() method. If you're trying to demonstrate that there are
multiple ways to compute powers, well...don't. Put that in a different
code sample.

-- The comment "One advantage of delegates over Events is that a
delegate can return a value directly" is simply false. An event can use
any delegate type, including one that returns a value.

Other than those things, as well as the general sloppiness of the code and
comments, I'd say the sample is fine as far as it goes. I still prefer
the actual MSDN documentation though. The MSDN stuff seems to have been
written by people with some actual experience in teaching and
documentation, and who actually know the material they are trying to teach.

No doubt you'll take offense at this reply, but frankly I think it's
something you need to see. This isn't the first time you've posted code
purporting to educate others, when in fact the code is a fairly poor
example of using C# and/or .NET (refer to your previous "static
inheritance" stuff, for example). If ever the phrase "some kinds of help,
we all can do without" applied, it's here.

Pete
Jul 13 '08 #8
On Jul 13, 9:32*am, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
>
No, I don't believe that code would ever have worked. You can't
declare another type inside a method, which is what you were trying to
do.
OK, that puts my mind at ease. I guess maybe I was confused with the
"lambda" business or whatever small nuiance regarding delegates that
C# 3.0 has which C# 2.0 doesn't.
>
Be aware that there's a big difference between declaring a delegate
*type* and declaring a *variable* of a delegate type.
Right, got that. We're talking about declaring a delegate type.

RL
Jul 13 '08 #9
raylopez99 <ra********@yahoo.comwrote:
No, I don't believe that code would ever have worked. You can't
declare another type inside a method, which is what you were trying to
do.

OK, that puts my mind at ease. I guess maybe I was confused with the
"lambda" business or whatever small nuiance regarding delegates that
C# 3.0 has which C# 2.0 doesn't.
Lambdas are rather more than a "small nuance", and type inference
improvements in C# 3 are pretty important when it comes to generic
delegates, too.
Be aware that there's a big difference between declaring a delegate
*type* and declaring a *variable* of a delegate type.

Right, got that. We're talking about declaring a delegate type.
That's what the statement you've got there does, yes. But both
anonymous methods and lambda expressions are about creating *instances*
of delegates.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon_skeet
C# in Depth: http://csharpindepth.com
Jul 13 '08 #10
On Jul 13, 5:03*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

[Lots of speculation and prolix dottage deleted]

We agree to disagree then.

In a few minutes I'll post in another thread an example showing
multiple interfaces, inhereitance override (including a bizarre effect
of 'new'), virtual functions and customizing IComparer, all rolled in
one example.

Good stuff.

RL
Jul 14 '08 #11
On Jul 15, 12:42*am, raylopez99 <raylope...@yahoo.comwrote:
In a few minutes I'll post in another thread an example showing
multiple interfaces, inhereitance override (including a bizarre effect
of 'new'), virtual functions and customizing IComparer, all rolled in
one example.
That will precisely miss Peter's point of: "You keep forgetting:
sample code should demonstrate one thing well, and not try to over-
complicate the rest."

It's a very good rule to teach by. (So is sticking to common naming
conventions, by the way. Being inconsistent and ignoring well-
established conventions *is* distracting, there's no doubt about it.)

Jon
Jul 15 '08 #12
On Jul 14, 11:01*pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
On Jul 15, 12:42*am, raylopez99 <raylope...@yahoo.comwrote:
In a few minutes I'll post in another thread an example showing
multiple interfaces, inhereitance override (including a bizarre effect
of 'new'), virtual functions and customizing IComparer, all rolled in
one example.

That will precisely miss Peter's point of: "You keep forgetting:
sample code should demonstrate one thing *well, and not try to over-
complicate the rest."

It's a very good rule to teach by. (So is sticking to common naming
conventions, by the way. Being inconsistent and ignoring well-
established conventions *is* distracting, there's no doubt about it.)

Jon
Jon, Peter made one good point in the whole thread, and, after
sleeping on it, I was inspired to find that indeed a multicast
delegate can be invoked to traverse the delegates in its chain
automatically, without the need of a 'foreach' statement.

Thus the below are equivalent.

foreach (DelegateClass.PublicHigherPower2 val in
CombinedDelegates01.GetInvocationList()) {
val.Invoke(111); //uses variable 111 as parameter (req'd)
}

//is: equivalent to: CombinedDelegates01(111);

RL
Jul 15 '08 #13
On Jul 15, 7:28*am, raylopez99 <raylope...@yahoo.comwrote:
That will precisely miss Peter's point of: "You keep forgetting:
sample code should demonstrate one thing *well, and not try to over-
complicate the rest."
It's a very good rule to teach by. (So is sticking to common naming
conventions, by the way. Being inconsistent and ignoring well-
established conventions *is* distracting, there's no doubt about it.)

Jon, Peter made one good point in the whole thread
I count two just in the bits that I quoted. I *strongly* urge you to
take notice of them, especially if you're going to post more
"teaching" articles. That's entirely leaving aside his technical
points around delegates.
and, after sleeping on it, I was inspired to find that indeed a multicast
delegate can be invoked to traverse the delegates in its chain
automatically, without the need of a 'foreach' statement.
Indeed. That's part of the point of them.

For more information about delegates, events, anonymous methods and
lambda expressions you might want to look at these articles:
http://pobox.com/~skeet/csharp/events.html
http://csharpindepth.com/Articles/Ch.../Closures.aspx

Jon
Jul 15 '08 #14
On Mon, 14 Jul 2008 16:42:44 -0700, raylopez99 <ra********@yahoo.com>
wrote:
On Jul 13, 5:03¬*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:

[Lots of speculation and prolix dottage deleted]
"Dottage"? Never heard of it.
We agree to disagree then.
You certainly may, at your own peril.

Pete
Jul 15 '08 #15
>>As for specific comments regarding your example, I'll start by pointing
>>out that MSDN has a MUCH MUCH better article introducing delegate
types:http://msdn.microsoft.com/en-us/libr...59(VS.71).aspx

Actually no. I reviewed this Microsoft example just now, and it has
the same defect as other examples I've seen.

Really? Your assertion is that the MSDN article is inferior to your own
posts on the topic?

Amusing. I'd be curious to see if there was even a single other person
who agrees with that assessment.
I will.

The MS article is full of pro-C# FUD.

The statement "Unlike function pointers in C or C++, delegates are
object-oriented, type-safe, and secure. " is misleading at best and most
likely blatantly false. C++ function pointers and object-oriented
(pointer-to-member anyone?) and type-safe. "Secure" doesn't have a
universally accepted definition.

I mean, why doesn't Microsoft push C# by saying "Unlike C++, C# can perform
file I/O, call third-party libraries, display fancy graphics, and run tasks
in parallel using multithreading."

Jul 15 '08 #16
On Tue, 15 Jul 2008 09:42:06 -0700, Ben Voigt [C++ MVP]
<rb*@nospam.nospamwrote:
>Really? Your assertion is that the MSDN article is inferior to your
own posts on the topic?

Amusing. I'd be curious to see if there was even a single other person
who agrees with that assessment.

I will.
Really? Your complaint, such as it is, leads you to feel that Ray's
contribution is a _superior_ resource to MSDN? That is, you would rather
learn about delegates from his post than MSDN's article?
The MS article is full of pro-C# FUD.
Seems you have a chip on your shoulder.
The statement "Unlike function pointers in C or C++, delegates are
object-oriented, type-safe, and secure. " is misleading at best and most
likely blatantly false. C++ function pointers and object-oriented
s/and/are ?
(pointer-to-member anyone?) and type-safe.
As far as I know, a C++ function pointer cannot encapsulate the target of
the reference, can it? Would you mind elaborating on what you mean by
"C++ function pointers are object-oriented"?
"Secure" doesn't have a universally accepted definition.
In the context of .NET, I would suspect that they mean that delegates
follow the same security rules as the rest of .NET's data security rules.
Why would you assume otherwise?
I mean, why doesn't Microsoft push C# by saying "Unlike C++, C# can
perform file I/O, call third-party libraries, display fancy graphics,
and run tasks in parallel using multithreading."
Well, none of those are language features per se. So that might be one
reason.

Pete
Jul 15 '08 #17
On Jul 15, 10:09*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
On Tue, 15 Jul 2008 09:42:06 -0700, Ben Voigt [C++ MVP] *

<r...@nospam.nospamwrote:
Really? *Your assertion is that the MSDN article is inferior to your*
own posts on the topic?
Amusing. *I'd be curious to see if there was even a single other person *
who agrees with that assessment.
I will.

Really? *Your complaint, such as it is, leads you to feel that Ray's *
contribution is a _superior_ resource to MSDN? *That is, you would rather *
learn about delegates from his post than MSDN's article?
Yes, that's what he said Peter. Because my program worked, as did the
MSDN program. If you are a professional programmer, you have to be
able to read and decypher other people's code, and sometimes that code
is written by a rank newbie like myself (btw I don't code for a
living, but the point is still made). If you can only read and
understand code written by an academic or by somebody who writes
simple code for MSDN articles, then you are a poor programmer indeed.
Speaking of poor programmer, I see Ben Voight has the prestigious [C++
MVP] abbreviation next to his name--funny, I don't see that next to
your name.
>
The MS article is full of pro-C# FUD.

Seems you have a chip on your shoulder.
No, seems like Ben is saying the MS article is full of pro-C# FUD, and
upon a closer reading, turns out he's right.
>
As far as I know, a C++ function pointer cannot encapsulate the target of*
the reference, can it? *Would you mind elaborating on what you mean by *
"C++ function pointers are object-oriented"?
Would you mind elaborating with "encapsulate the target of the
reference"--what do you mean by "encapsulate"? By "reference"--are
you talking about the reference operator "&" or something else? Seems
like a lot of people make up word terms then try and debate others
with this term in mind, "in their mind's eye", without the other
person even knowing what the debate is all about. Seems like that
happened a while ago with the statement about passing something by
reference in C#/CLI. Or so it seemed (in my mind's eye).
>
"Secure" doesn't have a universally accepted definition.

In the context of .NET, I would suspect that they mean that delegates *
follow the same security rules as the rest of .NET's data security rules.*
Why would you assume otherwise?
Perhaps he doesn't assume otherwise. Why do you assume he assumes
otherwise?
>
I mean, why doesn't Microsoft push C# by saying "Unlike C++, C# can *
perform file I/O, call third-party libraries, display fancy graphics, *
and run tasks in parallel using multithreading."

Well, none of those are language features per se. *So that might be one*
reason.
One reason for what? Ambiguity seems to be your friend, Pete (in your
mind's eye).

Ray
Jul 16 '08 #18
On Wed, 16 Jul 2008 01:12:19 -0700, raylopez99 <ra********@yahoo.com>
wrote:
>Really? ¬*Your complaint, such as it is, leads you to feel that Ray's ¬*
contribution is a _superior_ resource to MSDN? ¬*That is, you would
rather ¬*
learn about delegates from his post than MSDN's article?

Yes, that's what he said Peter.
No, he hasn't said so explicitly. That's why I asked for a clarification.
[...]
Speaking of poor programmer, I see Ben Voight has the prestigious [C++
MVP] abbreviation next to his name--funny, I don't see that next to
your name.
That's true, you don't. While I am in fact a recipient of the C# MVP
award, I choose not to include that in my posting credentials. So what?

By the way, if you're going to try to ride on Ben's coat-tails, you ought
to at least make the effort to spell his name correctly.
[...]
>As far as I know, a C++ function pointer cannot encapsulate the target
of ¬*
the reference, can it? ¬*Would you mind elaborating on what you mean by ¬*
"C++ function pointers are object-oriented"?

Would you mind elaborating with "encapsulate the target of the
reference"--what do you mean by "encapsulate"?
The delegate includes as part of itself the object that will be used in
invoking the method referenced by the delegate. In C++, if I recall
correctly (it's been at least five or six years since I did any serious
C++ programming), while you can in fact get a function pointer to an
instance method of a class, you still need to explicitly provide an
instance when calling the method. It can't be bound at the time the
function pointer is created, the way it is with a delegate in C#.

I'm sure Ben will correct me if I'm wrong about that, and if so I'll
welcome the correction. My concern is that the facts are correct, not
whose stream of urine can reach the farthest.
By "reference"--are
you talking about the reference operator "&" or something else?
I'm talking about a particular reference to an object.
Seems
like a lot of people make up word terms then try and debate others
with this term in mind, "in their mind's eye", without the other
person even knowing what the debate is all about.
My post was a reply to Ben and not at all intended for your consumption.
I doubt Ben would be as confused by the terms as you seem to have been.
Whether you understand it or not was of no concern to me, though I don't
mind explaining them to you or anyone else who didn't understand.
[...]
"Secure" doesn't have a universally accepted definition.

In the context of .NET, I would suspect that they mean that delegates ¬*
follow the same security rules as the rest of .NET's data security
rules. ¬*
Why would you assume otherwise?

Perhaps he doesn't assume otherwise. Why do you assume he assumes
otherwise?
I didn't assume. Ben's post makes clear that he's not choosing the
obvious, standard definition of security that exists in the context of
..NET.
I mean, why doesn't Microsoft push C# by saying "Unlike C++, C# can ¬*
perform file I/O, call third-party libraries, display fancy graphics,
and run tasks in parallel using multithreading."

Well, none of those are language features per se. ¬*So that might be one
reason.

One reason for what?
As an answer to the question "why doesn't Microsoft push C# by
saying...". I did quote the text to which I was responding, and you were
even so kind as to include that same text when you quoted my reply, so
there's really no reason for you to fail to understand.
Ambiguity seems to be your friend, Pete (in your
mind's eye).
I wasn't ambiguous. You simply failed to read (or comprehend) all the
words.

Pete
Jul 16 '08 #19
On Jul 16, 1:31*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
No, he hasn't said so explicitly. *That's why I asked for a clarification.
Well, you admit you're confused. Understood.
[...]
Speaking of poor programmer, I see Ben Voight has the prestigious [C++
MVP] abbreviation next to his name--funny, I don't see that next to
your name.

That's true, you don't. *While I am in fact a recipient of the C# MVP *
award, I choose not to include that in my posting credentials. *So what?
So you're perhaps not a C# MVP.
>
By the way, if you're going to try to ride on Ben's coat-tails, you ought*
to at least make the effort to spell his name correctly.
Ben Voight. That's his name.
>
Would you mind elaborating with "encapsulate the target of the
reference"--what do you mean by "encapsulate"?

The delegate includes as part of itself the object that will be used in *
invoking the method referenced by the delegate. *In C++, if I recall *
correctly (it's been at least five or six years since I did any serious *
C++ programming), while you can in fact get a function pointer to an *
instance method of a class, you still need to explicitly provide an *
instance when calling the method. *It can't be bound at the time the *
function pointer is created, the way it is with a delegate in C#.
Well that's news to me. I have no idea what you're talking about but
maybe Ben does.
I'm sure Ben will correct me if I'm wrong about that, and if so I'll *
welcome the correction. *My concern is that the facts are correct, not *
whose stream of urine can reach the farthest.
Looks like a flame thread or pissing contest to me, but I could be
wrong.
Seems
like a lot of people make up word terms then try and debate others
with this term in mind, "in their mind's eye", without the other
person even knowing what the debate is all about.

My post was a reply to Ben and not at all intended for your consumption. *
I doubt Ben would be as confused by the terms as you seem to have been. *
Whether you understand it or not was of no concern to me, though I don't *
mind explaining them to you or anyone else who didn't understand.
That's nice.
One reason for what?

As an answer to the question "why doesn't Microsoft push C# by *
saying...". *I did quote the text to which I was responding, and you were *
even so kind as to include that same text when you quoted my reply, so *
there's really no reason for you to fail to understand.
I still don't understand, but I'll let it pass.
>
Ambiguity seems to be your friend, Pete (in your
mind's eye).

I wasn't ambiguous. *You simply failed to read (or comprehend) all the *
words.
Or so it seems (in your mind's eye).

RL
Jul 16 '08 #20
On Wed, 16 Jul 2008 01:41:32 -0700, raylopez99 <ra********@yahoo.com>
wrote:
On Jul 16, 1:31¬*am, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
>No, he hasn't said so explicitly. ¬*That's why I asked for a
clarification.

Well, you admit you're confused.
No, I'm not. It's simply that the information is incomplete at this
point. There is, in fact, a difference.
Understood.
Obviously not.
[...]
Speaking of poor programmer, I see Ben Voight has the prestigious [C++
MVP] abbreviation next to his name--funny, I don't see that next to
your name.

That's true, you don't. ¬*While I am in fact a recipient of the C# MVP ¬*
award, I choose not to include that in my posting credentials. ¬*So what?

So you're perhaps not a C# MVP.
If that were true, I would not have written "I am in fact a recipient of
the C# MVP award".
>By the way, if you're going to try to ride on Ben's coat-tails, you
ought ¬*
to at least make the effort to spell his name correctly.

Ben Voight. That's his name.
No it's not. But, please...dig your hole as deep as you like.
[...]
>I'm sure Ben will correct me if I'm wrong about that, and if so I'll ¬*
welcome the correction. ¬*My concern is that the facts are correct, not ¬*
whose stream of urine can reach the farthest.

Looks like a flame thread or pissing contest to me, but I could be
wrong.
No "could be" about it. You simply are.

Pete
Jul 16 '08 #21
On Jul 16, 12:31*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
The delegate includes as part of itself the object that will be used in *
invoking the method referenced by the delegate. *In C++, if I recall *
correctly (it's been at least five or six years since I did any serious *
C++ programming), while you can in fact get a function pointer to an *
instance method of a class, you still need to explicitly provide an *
instance when calling the method. *It can't be bound at the time the *
function pointer is created, the way it is with a delegate in C#.
While this is definitely in the offtopic territory now, I'll still
clarify this, for what's it worth...

In C++, pointers to members are not closed over the receiver (i.e.
"this") - this includes both pointers to fields, and pointers to
methods. However, it is obviously trivial to take such an open
pointer, and close it over anything you wish, and there are plenty of C
++ libraries encapsulating this (boost::signal, libsig++, etc);
furthermore, ISO C++ TR1 includes a standard way to do this via
std::tr1::bind. In that way, raw pointers to members are not "object-
oriented" (though what it has to do with OOP as such escapes me), but
they provide a foundational mechanism to implement C#-style delegates.

On the other hand, it not possible to fully imitate the semantics of C+
+ pointers to members in C# using delegates; for example, when it
comes to virtual calls (in C++, calling a virtual function through a
member pointer to it involves full dynamic dispatch at the point of
the call; in C#, resolution happens when you instantiate the
delegate).

Then again, those MSDN claims that delegates are somehow "more object-
oriented" than C++ pointers to members reminds me of how, some time
ago, Java adepts complaned that delegates are "not object-oriented"
compared to Java-style listener interfaces.
Jul 17 '08 #22
>>As far as I know, a C++ function pointer cannot encapsulate the
>>target of
the reference, can it? Would you mind elaborating on what you mean
by "C++ function pointers are object-oriented"?
Simply that there's a variant of function pointers, the pointer-to-member
function pointer, which is designed solely for use with objects.
>>
Would you mind elaborating with "encapsulate the target of the
reference"--what do you mean by "encapsulate"?

The delegate includes as part of itself the object that will be used
in invoking the method referenced by the delegate. In C++, if I
recall correctly (it's been at least five or six years since I did
any serious C++ programming), while you can in fact get a function
pointer to an instance method of a class, you still need to
explicitly provide an instance when calling the method. It can't be
bound at the time the function pointer is created, the way it is with
a delegate in C#.
I'm sure Ben will correct me if I'm wrong about that, and if so I'll
welcome the correction. My concern is that the facts are correct, not
whose stream of urine can reach the farthest.
C++ can do that, but you'd be using a functor at that point, not a raw
function pointer. I think boost::bind is the most widely used method to
accomplish that, and unlike .NET delegates, boost::bind can close the call
on any combination of arguments, not just the first.
Jul 17 '08 #23
>>By the way, if you're going to try to ride on Ben's coat-tails, you
>>ought
to at least make the effort to spell his name correctly.

Ben Voight. That's his name.

No it's not. But, please...dig your hole as deep as you like.
Just to set the record straight, Peter is right, Ray keeps slipping in an
extra 'h', and there seems to be no confusion whatsoever who is being
referenced.
Jul 17 '08 #24
On Thu, 17 Jul 2008 00:58:05 -0700, Pavel Minaev <in****@gmail.comwrote:
[...]
On the other hand, it not possible to fully imitate the semantics of C+
+ pointers to members in C# using delegates; for example, when it
comes to virtual calls (in C++, calling a virtual function through a
member pointer to it involves full dynamic dispatch at the point of
the call; in C#, resolution happens when you instantiate the
delegate).
I think the C# designers consider that a feature. :)
Then again, those MSDN claims that delegates are somehow "more object-
oriented" than C++ pointers to members reminds me of how, some time
ago, Java adepts complaned that delegates are "not object-oriented"
compared to Java-style listener interfaces.
I agree that saying something is or is not "OOP" is difficult to justify,
given how it depends entirely on what standard of "OOP" one is referring
to.

My main point is that I honestly don't see the article as being rife with
"fear, uncertainty, and doubt" at all, never mind to the degree that would
invalidate it as a useful learning tool.

Pete
Jul 17 '08 #25
On Jul 18, 5:55*pm, raylopez99 <raylope...@yahoo.comwrote:
Regarding delegates used as events in the .NET framework--I've
discovered (for me) a shocking non-standard way that events are fired
when using the System.EventArgs class, which apparently is manditory,
as is the "On" prefix for any member function that uses an "EventArgs"
While databinding may take more notice of On* methods, the language
itself couldn't care less. They're just normal methods. Likewise the
language doesn't know anything about EventArgs or EventHandler.

Now, as for the syntax used for creating delegate instances, this is
just a new feature as of C# 2 - implicit conversion of method groups
to delegate instances.

See http://www.csharpindepth.com/Article...ersGuide2.aspx

Jon
Jul 18 '08 #26
On Jul 18, 10:02*am, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
While databinding may take more notice of On* methods, the language
itself couldn't care less. They're just normal methods. Likewise the
language doesn't know anything about EventArgs or EventHandler.
Fair enough, but this is a .NET group so I imply that it's the NET API
that knows this stuff, through databinding (whatever that is, but I
think it's the stuff Alan Cooper invented with Visual drag and drop
code generated by the wizard).
>
Now, as for the syntax used for creating delegate instances, this is
just a new feature as of C# 2 - implicit conversion of method groups
to delegate instances.

Seehttp://www.csharpindepth.com/Articles/General/BluffersGuide2.aspx
That was good, thanks. I wish I had a bluffer's guide to C# (I've
bought some of their guides in the past for other stuff)

RL

Delegates in C# 2 have a number of improvements over C# 1. The most
important two features are implicit method group conversions and
anonymous methods, both of which make it easier to create new
instances of delegate types. For example:

public void Foo()
{
// Do some stuff
}

// C# 1 code:
ThreadStart ts1 = new ThreadStart(Foo);

// C# 2 code, implicit method group conversion:
ThreadStart ts2 = Foo;

// C# 2, anonymous method:
ThreadStart ts3 = delegate { Console.WriteLine("Hi!"); };

There's a lot more to anonymous methods than meets the eye, by the
way...
Jul 18 '08 #27
On Jul 18, 8:55*pm, raylopez99 <raylope...@yahoo.comwrote:
Shocking stuff dontyathink?
Not at all. Aside from a number of things that you've simply got wrong
(such as "On..." methods and EventArgs-style signatures for events
being required), it's all very basic C#, discussed in detail in pretty
much every entry-level book.

By the way, it might be a good idea to check whether this is also true
(as it seems to be for your posts so far, invariably) for whatever it
is you're going to post next. Perhaps it's not worth the bother, after
all.
Jul 18 '08 #28
raylopez99 <ra********@yahoo.comwrote:
While databinding may take more notice of On* methods, the language
itself couldn't care less. They're just normal methods. Likewise the
language doesn't know anything about EventArgs or EventHandler.

Fair enough, but this is a .NET group so I imply that it's the NET API
that knows this stuff, through databinding (whatever that is, but I
think it's the stuff Alan Cooper invented with Visual drag and drop
code generated by the wizard).
But my point is that it's only very specific bits of .NET which care
about how you name event raising methods. For the most part, you can
call them what you like with no ill effects other than breaking
convention.

In particular, your claim that:

<quote>
Eventhandler delegates used in a class can (it's complicated) use a
protected virtual method that fires the event but must have prefix "On"
as the name of the method.
</quote>

is incorrect in the general case.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon_skeet
C# in Depth: http://csharpindepth.com
Jul 18 '08 #29
On Jul 18, 4:33*pm, Pavel Minaev <int...@gmail.comwrote:
On Jul 18, 8:55*pm, raylopez99 <raylope...@yahoo.comwrote:
Shocking stuff dontyathink?

Not at all. Aside from a number of things that you've simply got wrong
(such as "On..." methods and EventArgs-style signatures for events
being required), it's all very basic C#, discussed in detail in pretty
much every entry-level book.
Hay bozo: I said: "events are fired when using the System.EventArgs
class, which apparently is manditory,
as is the "On" prefix for any member function that uses an "EventArgs"
type delegate. "

Refute that?
By the way, it might be a good idea to check whether this is also true
(as it seems to be for your posts so far, invariably) for whatever it
is you're going to post next. Perhaps it's not worth the bother, after
all.
Perhaps you can killfile me and avoid having the reply, since you're
obsessive compulsive. Or just take your 20 mg Prozac, like your
doctor says.

RL
Jul 19 '08 #30
On Jul 18, 4:35*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
In particular, your claim that:

<quote>
Eventhandler delegates used in a class can (it's complicated) use a
protected virtual method that fires the event but must have prefix "On"
as the name of the method.
</quote>

is incorrect in the general case.
Perhaps the prefix "On" is, I agree. But it seems to me EventArgs-
style signatures have a particular format. I will experiment with
this in Console mode and if there's anything of interest will post a
sample program for future generations to ponder later today.

RL
Jul 19 '08 #31
On Jul 19, 2:11*pm, raylopez99 <raylope...@yahoo.comwrote:
Hay bozo: *I said: "events are fired when using the System.EventArgs
class, which apparently is manditory,
It is _not_ mandatory.
as is the "On" prefix for any member function that uses an "EventArgs"
type delegate. "
And neither is this.

With regard to "proof", I can only refer you to the C# 3.0 Language
Specification, available directly from Microsoft:

http://msdn.microsoft.com/en-us/vcsharp/aa336809.aspx

If you can find anything at all in it regarding EventArgs or "On..."
being mandatory, you're welcome to share it with me. In fact, it would
be interesting if you can find any mention of EventArgs whatsoever
aside from the (non-normative) code samples.
Jul 19 '08 #32
raylopez99 <ra********@yahoo.comwrote:
Hay bozo: I said: "events are fired when using the System.EventArgs
class, which apparently is manditory,
as is the "On" prefix for any member function that uses an "EventArgs"
type delegate. "

Refute that?
Very easily:

using System;

class Test
{
public event Action Foo;
public event EventHandler Bar;

protected void FireBar(EventArgs args)
{
Bar(this, args);
}

static void Main()
{
Test t = new Test();
t.Foo += () =Console.WriteLine("First");
t.Bar += (sender, args) =Console.WriteLine("Second");

t.Foo();
t.FireBar(EventArgs.Empty);
}
}

Note that "FireBar" doesn't begin with "On", and "Foo" is an event
which doesn't use EventArgs.
By the way, it might be a good idea to check whether this is also true
(as it seems to be for your posts so far, invariably) for whatever it
is you're going to post next. Perhaps it's not worth the bother, after
all.

Perhaps you can killfile me and avoid having the reply, since you're
obsessive compulsive. Or just take your 20 mg Prozac, like your
doctor says.
Some of us just care about accuracy, that's all. It would also be
preferable to avoid the ad hominem attacks.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 19 '08 #33
raylopez99 <ra********@yahoo.comwrote:
Perhaps the prefix "On" is, I agree. But it seems to me EventArgs-
style signatures have a particular format. I will experiment with
this in Console mode and if there's anything of interest will post a
sample program for future generations to ponder later today.
Any delegate instance of the type EventHandler has to have the right
signature, yes - but that's true of all delegate types. The type
defines the required (or at least compatible) signature. EventHandler's
signature is
void EventHandler(object sender, EventArgs e)
but there's nothing magical about it - that's just how it's been
defined.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 19 '08 #34
On Jul 19, 6:33*am, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
>
using System;

class Test
{
* * public event Action Foo;
* * public event EventHandler Bar;

* * protected void FireBar(EventArgs args)
* * {
* * * * Bar(this, args);
* * }

* * static void Main()
* * {
* * * * Test t = new Test();
* * * * t.Foo += () =Console.WriteLine("First");
* * * * t.Bar += (sender, args) =Console.WriteLine("Second");

* * * * t.Foo();
* * * * t.FireBar(EventArgs.Empty);
* * }

}

Note that "FireBar" doesn't begin with "On", and "Foo" is an event
which doesn't use EventArgs.
Note: this example did not compile (10 errors). Some errors were
easy to fix (I think), like adding <intin public event Action <int>
Foo, but some, like you "lambda expression" is incomprehensible to
me. Can you please drop the =expression and give a cleaner
example? I'd like to go through it and learn something.
Some of us just care about accuracy, that's all. It would also be
preferable to avoid the ad hominem attacks.
Yes, I hear you, but I think you're just too sensitive. The other
dude didn't complain, but I'll tone it down some.

RL
Jul 19 '08 #35
On Jul 19, 4:02*am, Pavel Minaev <int...@gmail.comwrote:
On Jul 19, 2:11*pm, raylopez99 <raylope...@yahoo.comwrote:
Hay bozo: *I said: "events are fired when using the System.EventArgs
class, which apparently is manditory,

It is _not_ mandatory.
Yes, it is (in my mind's eye). We are talking about two different
things. See the post by Jon Skeet--he has what I have in mind. Never
mind his example doesn't compile. The issue is: when you use
EventArgs, is there a particular format? yes there is. The book
C#3.0 Nutshell by Albahari et al states: "With an EventArgs subclass
in place, ...there are three rules: 1/ it must have a void return
type 2/ it must accept two arguments, the first of type object, adn
the second a subclass of EventArgs; the first argument, object,
indicates the event broadcaster, and the second argument contains the
extra information to convey. 3/ Its name must end in "EventHandler".

Now that's what the book sez. It could be 'convention', or, it could
be manditory. In my mind's eye it's the same thing.

Sorry to flame you BTW, but I found I get more responses on usenet
when I'm rude. I'll tone it down a bit because Jon and Peter are
sensitive souls.

RL
Jul 19 '08 #36
raylopez99 <ra********@yahoo.comwrote:
Note that "FireBar" doesn't begin with "On", and "Foo" is an event
which doesn't use EventArgs.

Note: this example did not compile (10 errors).
It compiles perfectly for me. Perhaps you're not using a C# 3 compiler,
or .NET 3.5?
Some errors were
easy to fix (I think), like adding <intin public event Action <int>
Ah, that strongly suggests you've only got .NET 2.0 or 3.0 installed.
Foo, but some, like you "lambda expression" is incomprehensible to
me. Can you please drop the =expression and give a cleaner
example? I'd like to go through it and learn something.
Here's a version which will (I believe) compile with .NET 2.0.

using System;

class Test
{
public event Action<intFoo;
public event EventHandler Bar;

protected void FireBar(EventArgs args)
{
Bar(this, args);
}

static void Main()
{
Test t = new Test();
t.Foo += delegate { Console.WriteLine("First"); };
t.Bar += delegate { Console.WriteLine("Second"); };

t.Foo(10);
t.FireBar(EventArgs.Empty);
}
}
Some of us just care about accuracy, that's all. It would also be
preferable to avoid the ad hominem attacks.

Yes, I hear you, but I think you're just too sensitive. The other
dude didn't complain, but I'll tone it down some.
I hope so - because you're being *incredibly* rude. You just don't
start calling people "bozo" and recommending they take Prozac - it's
not the way things are done in polite discussions. It's not like this
is the first ad hominem attack you've launched, either. Just because
other people may not respond doesn't make your approach any more
palatable. Bear in mind that you're asking people to help you here -
insulting them isn't going to get you anywhere. Would you act like this
in real life?

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 19 '08 #37
raylopez99 <ra********@yahoo.comwrote:
Hay bozo: *I said: "events are fired when using the System.EventArgs
class, which apparently is manditory,
It is _not_ mandatory.
Yes, it is (in my mind's eye). We are talking about two different
things.
In that case you haven't explained yourself clearly enough. Your
statement that "events are fired when using the System.EventArgs class,
which apparently is mandatory" is wrong in itself. Yes, you have to use
EventArgs for an event *of type EventHandler* but that's a very
different statement.
See the post by Jon Skeet--he has what I have in mind. Never
mind his example doesn't compile.
It does, just not under C# 2. Given that you're reading C# 3.0 in a
Nutshell, it would really help you to have a C# 3 compiler installed.
The issue is: when you use
EventArgs, is there a particular format? yes there is. The book
C#3.0 Nutshell by Albahari et al states: "With an EventArgs subclass
in place, ...there are three rules: 1/ it must have a void return
type 2/ it must accept two arguments, the first of type object, adn
the second a subclass of EventArgs; the first argument, object,
indicates the event broadcaster, and the second argument contains the
extra information to convey. 3/ Its name must end in "EventHandler".
What you didn't explain is that it's under a heading of "Standard Event
Pattern". The pattern is *not* enforced by anything, it's just a
convention. It's worth being very clear about the difference between
patterns/conventions and what is valid code.

It's valid to declare a property with the name @int - but it would be
daft to do so, and violate naming conventions left, right and centre.
Now that's what the book sez. It could be 'convention', or, it could
be manditory. In my mind's eye it's the same thing.
Then your "mind's eye" is incorrect. There's a difference between a
*requirement* and a *recommendation*.
Sorry to flame you BTW, but I found I get more responses on usenet
when I'm rude. I'll tone it down a bit because Jon and Peter are
sensitive souls.
You may get more of a response in terms of *volume* when you're rude,
but you'll find that you actually *learn* a lot more quickly when
you're polite, because people don't need to waste time trying to teach
you manners.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 19 '08 #38
On Jul 19, 8:39*am, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
raylopez99 <raylope...@yahoo.comwrote:
Note that "FireBar" doesn't begin with "On", and "Foo" is an event
which doesn't use EventArgs.
Note: *this example did not compile (10 errors).

It compiles perfectly for me. Perhaps you're not using a C# 3 compiler,
or .NET 3.5?
Using 2.0. I rewrote your code to conform with my "old style" and it
works. See below. I don't know what "Action" (a keyword) means, and
your use of 'anonymous' or 'inline' delegates is not for me, though I
understand you can 'capture code' and make it sort of a local variable
that way, though looks too confusing to get into. Note also you have
to input something for EventHandler, namely,
t.FireBar(EventArgs.Empty), so you have to input .Empty, which is
something I agree with, and I think you do too. But you made your
point, and I understand it and was apparently mistaking "convention"
with a hard and fast rule about EventHandler. Thanks for clearing
that up.
namespace DelegateSimple01
{

class Test
{
public delegate void FooEventHandler(int i);

//public event Action<intFoo;
public event FooEventHandler Fool;
public event EventHandler Bar;
protected void FireBar(EventArgs args)
{
Bar(this, args);
}
static void Main()
{
Test t = new Test();
//t.Foo += delegate { Console.WriteLine("First"); };

t.Fool += new FooEventHandler(Foo);
t.Bar += delegate { Console.WriteLine("Second"); };

t.Fool(10);
t.FireBar(EventArgs.Empty);
}
static void Foo(int ii)
{
Console.WriteLine("First,hello!");
}
}

}

>
Yes, I hear you, but I think you're just too sensitive. *The other
dude didn't complain, but I'll tone it down some.

I hope so - because you're being *incredibly* rude. You just don't
start calling people "bozo" and recommending they take Prozac - it's
not the way things are done in polite discussions.
Yes, but this is Usenet.

It's not like this
is the first ad hominem attack you've launched, either. Just because
other people may not respond doesn't make your approach any more
palatable. Bear in mind that you're asking people to help you here -
insulting them isn't going to get you anywhere. Would you act like this
in real life?
Yes, sometimes. And it doesn't hurt. In fact, a study once found that
people who are "jerks" end up with little or no negative things
happening to their career. Early in my career, straight out of
school, one of my bosses, who had real clout, once told me: "after you
leave here [he fired me] you'll never work in this field again, I'll
make sure of it" (because of his prestigious position, even if you
wanted to you could not easily sue him for defamation, not that I
would sue him, since I don't believe in lawsuits). He tried his best,
giving me negative recommendations, and despite him I got a better job
and never looked back. But, that does not mean you should be a jerk--
being nice, as I learned in California, gets the job done easier
(Persian expression about honey attracting flies--then again, shitte
attracts flies too)--but at the end of the day, the nice guys, bad
guys, jerks (good, bad and ugly) end up roughly in the same place,
inline with fortune, fate, and their own innate abilities. However,
having said that, since I appreciate your input and feel you might
stop replying to me, I will tone it down some. Like you say you're
not being paid to answer me.

Thanks for your help. I appreciate it and you've done a lot of good
over the years replying to people (I see some of your posts in the
archives when I Google an answer to a problem).

RL
Jul 19 '08 #39
On Jul 19, 9:02*pm, raylopez99 <raylope...@yahoo.comwrote:
Using 2.0. *I rewrote your code to conform with my "old style" and it
works. *See below. *I don't know what "Action" (a keyword) means
It's not a keyword. It's System.Action<Tdelegate type declared like
this:

delegate void Action<T>(T arg);

So, basically, a general type for single-argument procedures.

Jon's original code used System.Action (without T), which was
introduced in .NET 3.5, and is essentially a no-argument version of
the above:

delegate void Action();
Jul 19 '08 #40
On Jul 19, 10:02*am, raylopez99 <raylope...@yahoo.comwrote:
namespace DelegateSimple01
{

* * class Test
* * {
* * * * public delegate void FooEventHandler(int i);

* * * * //public event Action<intFoo;
* * * * public event FooEventHandler Fool;
* * * * public event EventHandler Bar;
* * * * protected void FireBar(EventArgs args)
* * * * {
* * * * * * Bar(this, args);
* * * * }
* * * * static void Main()
* * * * {
* * * * * * Test t = new Test();
* * * * * * //t.Foo += delegate { Console.WriteLine("First"); };

* * * * * * t.Fool += new FooEventHandler(Foo);
* * * * * * t.Bar += delegate { Console.WriteLine("Second"); };

* * * * * * t.Fool(10);
* * * * * * t.FireBar(EventArgs.Empty);

* * * * }
* * * * static void Foo(int ii)
* * * * {
* * * * * * Console.WriteLine("First,hello!");
* * * * }
* * }

}
I discovered a 'required' convention that should be followed for
delegates:

the class event handler registering the event, here, t.Fool += new
FooEventHandler(Foo); or, equivalently, t.Fool += Foo; [*1*] should
have the target method that accepts the parameter, namely the method
Foo (here: static void Foo(int ii)
{ Console.WriteLine("First,hello!"); }), in the same class scope as
the class that contains the class event handler (i.e. [*1*] above),
here, Test.

Otherwise, it won't compile. This holds true in Windows Forms too,
and trying to use a scope resolution operators like
"ExternalFormClass.Foo" to get to another class in another form did
not work, so, dare I say it, it must be kind of like a "requirement",
using the term loosely. Anyway I don't see the harm doing it this
'required' way, even if it's not a requirement.

RL
Jul 20 '08 #41
raylopez99 <ra********@yahoo.comwrote:
I discovered a 'required' convention that should be followed for
delegates:

the class event handler registering the event, here, t.Fool += new
FooEventHandler(Foo); or, equivalently, t.Fool += Foo; [*1*] should
have the target method that accepts the parameter, namely the method
Foo (here: static void Foo(int ii)
{ Console.WriteLine("First,hello!"); }), in the same class scope as
the class that contains the class event handler (i.e. [*1*] above),
here, Test.

Otherwise, it won't compile.
The part about having the right parameters is a requirement. The part
about being in the same class isn't. The method has to be accessible
though.

Note that this is only incidentally part of events - it's just to do
with how delegate instances are created. Here's an example creating two
Action<intinstances using methods in a different class - one of which
is an instance method and one of which is a static method.

using System;

class Foo
{
string name;

public Foo(string name)
{
this.name = name;
}

public static void Print(int i)
{
Console.WriteLine("Static: {0}", i);
}

public void PrintWithName(int i)
{
Console.WriteLine("Instance ({0}): {1}", name, i);
}
}

class Test
{
static void Main()
{
Foo f = new Foo("Bar");
Action<intstaticAction = Foo.Print;
Action<intinstanceAction = f.PrintWithName;

staticAction(1);
instanceAction(2);
}
}
This holds true in Windows Forms too,
and trying to use a scope resolution operators like
"ExternalFormClass.Foo" to get to another class in another form did
not work, so, dare I say it, it must be kind of like a "requirement",
using the term loosely. Anyway I don't see the harm doing it this
'required' way, even if it's not a requirement.
I do, if it means code duplication. If you have the required method
available and accessible somewhere else, it would be a pain to have to
copy the code.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 20 '08 #42
On Jul 20, 10:18*am, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
raylopez99 <raylope...@yahoo.comwrote:
I discovered a 'required' convention that should be followed for
delegates:
the class event handler registering the event, here, t.Fool += new
FooEventHandler(Foo); or, equivalently, t.Fool += Foo; [*1*] should
have the target method that accepts the parameter, namely the method
Foo (here: *static void Foo(int ii)
{ *Console.WriteLine("First,hello!"); *}), in the same class scope as
the class that contains the class event handler (i.e. [*1*] above),
here, Test.
Otherwise, it won't compile.

The part about having the right parameters is a requirement. The part
about being in the same class isn't. The method has to be accessible
though.
This is true--but perhaps my problem is this (this is a general
question): how do you access (what scope resolution operator, to use
a C++ term) do you use when you are trying to access a class declared
in a child form from the parent form? As I type this, I believe this
might be impossible in the general case, since the child form might be
instantiated by the parent form and "doesn't exist" unless
instantiated, but I guess we can have two scenarios: one being a
static child form that is already instantiated and the other being a
non-static 'new' child form.

Actually to make the question a bit broader (since I'm learning) how
do you access a class declared in the parent form, from the child
form? I haven't done this, but since a child inhereits the parent I
would imagine it's simply: //from inside the child form:
parentform.parentclass.someMethod(). This second question should be
straightforward.
>
Note that this is only incidentally part of events - it's just to do
with how delegate instances are created. Here's an example creating two
Action<intinstances using methods in a different class - one of which
is an instance method and one of which is a static method.
Thanks, but I didn't see how this is relevant, but it reminds me to
study 'Action' at some point, which looks like a sort of macro
shorthand.

This holds true in Windows Forms too,
and trying to use a scope resolution operators like
"ExternalFormClass.Foo" to get to another class in another form did
not work, so, dare I say it, it must be kind of like a "requirement",
using the term loosely. *Anyway I don't see the harm doing it this
'required' way, even if it's not a requirement.

I do, if it means code duplication. If you have the required method
available and accessible somewhere else, it would be a pain to have to
copy the code.
Perhaps, but the assumption is that you can access this code with a
scope resolution operator. But, if you cannot (see my first question
above) then it's safer to simply recopy the function XYZ that is being
registered into the current class. I.e.--
ParentForm_class1.AnEventHandler += XYZ; //with the understanding XYZ
belongs to 'ParentForm_class1'. If, however, XYZ belongs to the child
form, ChildForm, which may never be instantiated, what then? You
cannot do this: ParentForm_class1.AnEventHandler += ChildForm.XYZ;
in the general case, can you? I don't think so, in the most general
case of 'on-the-fly' child form instantiation from the parent form.

RL
Jul 20 '08 #43
raylopez99 <ra********@yahoo.comwrote:
Otherwise, it won't compile.
The part about having the right parameters is a requirement. The part
about being in the same class isn't. The method has to be accessible
though.
This is true--but perhaps my problem is this (this is a general
question): how do you access (what scope resolution operator, to use
a C++ term) do you use when you are trying to access a class declared
in a child form from the parent form? As I type this, I believe this
might be impossible in the general case, since the child form might be
instantiated by the parent form and "doesn't exist" unless
instantiated, but I guess we can have two scenarios: one being a
static child form that is already instantiated and the other being a
non-static 'new' child form.
I don't think you're using the right terminology for a fair amount of
that paragraph, so a code sample would be helpful.
Actually to make the question a bit broader (since I'm learning) how
do you access a class declared in the parent form, from the child
form? I haven't done this, but since a child inhereits the parent I
would imagine it's simply: //from inside the child form:
parentform.parentclass.someMethod(). This second question should be
straightforward.
Again, code would be helpful. I suspect that when you say "a class
declared in the parent form" you mean "a variable declared in the
parent form" but I don't even know whether you mean "parent" in an
inheritance sense or not.
Note that this is only incidentally part of events - it's just to do
with how delegate instances are created. Here's an example creating two
Action<intinstances using methods in a different class - one of which
is an instance method and one of which is a static method.
Thanks, but I didn't see how this is relevant
It's relevant because it means you can separate learning about events
from learning about delegates.
but it reminds me to study 'Action' at some point, which looks like a
sort of macro shorthand.
It's not. But if you mean the <Tpart, that's generics - which is a
whole other topic.
This holds true in Windows Forms too,
and trying to use a scope resolution operators like
"ExternalFormClass.Foo" to get to another class in another form did
not work, so, dare I say it, it must be kind of like a "requirement",
using the term loosely. *Anyway I don't see the harm doing it this
'required' way, even if it's not a requirement.
I do, if it means code duplication. If you have the required method
available and accessible somewhere else, it would be a pain to have to
copy the code.
Perhaps, but the assumption is that you can access this code with a
scope resolution operator.
There's no such operator in C#.
But, if you cannot (see my first question
above) then it's safer to simply recopy the function XYZ that is being
registered into the current class. I.e.--
ParentForm_class1.AnEventHandler += XYZ; //with the understanding XYZ
belongs to 'ParentForm_class1'. If, however, XYZ belongs to the child
form, ChildForm, which may never be instantiated, what then? You
cannot do this: ParentForm_class1.AnEventHandler += ChildForm.XYZ;
in the general case, can you? I don't think so, in the most general
case of 'on-the-fly' child form instantiation from the parent form.
Again, some actual code to talk about would be helpful.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 21 '08 #44
On Jul 20, 10:15*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
>
Again, code would be helpful. I suspect that when you say "a class
declared in the parent form" you mean "a variable declared in the
parent form" but I don't even know whether you mean "parent" in an
inheritance sense or not.
OK, let's call it a variable. A variable declared in the parent form,
but not part of any class. This can be 'found' (scope) in the child
form, yes? I think so. But a variable declared in the child, can it
be found (in the scope) of the parent form? The same problem arises
in Visual Basic when coding for Access dB, and they use dot operator
to resolve scope issues.
but it reminds me to study 'Action' at some point, which looks like a
sort of macro shorthand.

It's not. But if you mean the <Tpart, that's generics - which is a
whole other topic.
No, I meant the keyword 'Action', but it's off topic.

>
Perhaps, but the assumption is that you can access this code with a
scope resolution operator.

There's no such operator in C#.
I know. But if you know C++, the :: would be understood as global
scope. But let's not get hung up in lingo.
>
But, if you cannot (see my first question
above) then it's safer to simply recopy the function XYZ that is being
registered into the current class. *I.e.--
ParentForm_class1.AnEventHandler += XYZ; *//with the understanding XYZ
belongs to 'ParentForm_class1'. *If, however, XYZ belongs to the child
form, ChildForm, which may never be instantiated, what then? *You
cannot do this: *ParentForm_class1.AnEventHandler += ChildForm.XYZ;
in the general case, can you? *I don't think so, in the most general
case of 'on-the-fly' *child form instantiation from the parent form.

Again, some actual code to talk about would be helpful.
That was the actual code.
"You cannot do this: ParentForm_class1.AnEventHandler +=
ChildForm.XYZ; in the general case, can you? "

The assumption being ChildForm inhereits from Parent form. Frankly
it's a trivial point, if you abide by my 'convention' that I posted
earlier--and every example I've seen in the books abide by this
convention-- you don't need to use a dot operator to give the proper
scope, and using intelliSense, you simply write:
ParentForm_class1.AnEventHandler += .XYZ; since XYZ exists somewhere
as a function in a class in the parent form.

RL
Jul 21 '08 #45
On Jul 21, 12:12*pm, raylopez99 <raylope...@yahoo.comwrote:
Again, code would be helpful. I suspect that when you say "a class
declared in the parent form" you mean "a variable declared in the
parent form" but I don't even know whether you mean "parent" in an
inheritance sense or not.

OK, let's call it a variable. *A variable declared in the parent form,
but not part of any class.
How can it be part of a form but not part of a class? Again, please
show some code.
>*This can be 'found' (scope) in the child
form, yes?
Depends on its accessibility. (Personally I try to avoid using fields
which aren't private.)
*I think so. *But a variable declared in the child, can it
be found (in the scope) of the parent form? *
How could it be?
but it reminds me to study 'Action' at some point, which looks like a
sort of macro shorthand.
It's not. But if you mean the <Tpart, that's generics - which is a
whole other topic.

No, I meant the keyword 'Action', but it's off topic.
Action isn't a keyword at all. It's just a delegate type. The C#
compiler has no special knowledge about it.
Perhaps, but the assumption is that you can access this code with a
scope resolution operator.
There's no such operator in C#.

I know. *But if you know C++, the :: would be understood as global
scope. *But let's not get hung up in lingo.
You're making an assumption about C# based on an operator which
doesn't exist in C#. It's impossible to try to correct any mistakes in
your understanding on that basis.
Again, some actual code to talk about would be helpful.

That was the actual code.
"You cannot do this: *ParentForm_class1.AnEventHandler +=
ChildForm.XYZ; in the general case, can you? *"
And the answer is "You can if XYZ is an accessible static method with
the right signature."
The assumption being ChildForm inhereits from Parent form. *Frankly
it's a trivial point, if you abide by my 'convention' that I posted
earlier--and every example I've seen in the books abide by this
convention-- you don't need to use a dot operator to give the proper
scope, and using intelliSense, you simply write:
ParentForm_class1.AnEventHandler += .XYZ; *since XYZ exists somewhere
as a function in a class in the parent form.
That will never work, as ".XYZ" isn't valid. Or do you mean that's
just the sequence you type, and Intellisense turns it into something
else?

Jon
Jul 21 '08 #46
I have been closely following this thread these days. Is it the case
that at the end of the day, delegate is only useful in event handling?

I experimented with multicast delegate with the following code, but
got an exception which says: Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.

The code itself seems to be OK. What does this exception really
mean?

BTW, I don't understand how useful multicast delegate can be. It
seems to me that its only purpose is to "simplify" calling multiple
methods with one call. But all methods have to have the same
signature and all of them have to be registered with the given
multicast delegate. Plus, how often does it happen that multiple
methods have the same signature, return void, and need to be called
one after another? Maybe there are such typical situations in
software development which I don't know?

using System;

namespace ConsoleApplication1
{
public delegate void MulticastDelegate(string s1, string s2);
class MulticastDelegateTest
{
public static void Main(string[] args)
{
MulticastDelegate md = new MulticastDelegate(Method1);
md += new MulticastDelegate(Method2);
md("Just ", "a test.");
Console.ReadKey();
}
public static void Method1(string s1, string s2)
{
Console.WriteLine("M1: " + s1 + s2);
}

public static void Method2(string s1, string s2)
{
Console.WriteLine("M2: " + s1 + s2);
}
}
}
Jul 21 '08 #47
On Mon, 21 Jul 2008 07:47:00 -0700, Author <gn********@gmail.comwrote:
I have been closely following this thread these days. Is it the case
that at the end of the day, delegate is only useful in event handling?
No. I agree that a _multicast_ delegate is most commonly useful for event
handling. But delegates in general are useful in a much broader variety
of scenarios. Any time that you have code that wants to be able to
execute some arbitrary code without knowing what that code is at compile
time, a delegate is useful.

A couple of obvious examples include threaded invocations of code (see
ThreadStart) and collection processing (for example, predicates used for
searching, removing, or otherwise processing a collection).
I experimented with multicast delegate with the following code, but
got an exception which says: Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.

The code itself seems to be OK. What does this exception really
mean?
I don't know...I admit, at first glance the code looks fine to me. But
then, I've been having trouble just "reading" code lately, and I haven't
had a chance to actually try compiling and running it yet. So maybe I've
overlooked something.
BTW, I don't understand how useful multicast delegate can be. It
seems to me that its only purpose is to "simplify" calling multiple
methods with one call. But all methods have to have the same
signature and all of them have to be registered with the given
multicast delegate. Plus, how often does it happen that multiple
methods have the same signature, return void, and need to be called
one after another? Maybe there are such typical situations in
software development which I don't know?
As I mentioned, I think that events are the most obvious and most common
example of the use for multicast delegates. That's a clear example of a
situation in which one might want multiple methods all with the same
signature to all be executed at the same point in code.

You ask "how often does it happen...?" Depending on what you mean, it
happens regularly, or it's not very common. In the sense that events
depend on that model and they are the fundamental basis for a variety of
classes in .NET, including the Forms.Control class, as well as
BackgroundWorker and various Timer classes. But it's true that often
those events only have one method subscribed, and of course outside of
events the use of a multicast delegate may well be much less common.

But it does happen. :) Not everything in C#/.NET is there for the 90%
scenarios.

Pete
Jul 21 '08 #48
On Jul 21, 3:47 pm, Author <gnewsgr...@gmail.comwrote:
I have been closely following this thread these days. Is it the case
that at the end of the day, delegate is only useful in event handling?
No, not at all. Delegates have become more useful over the course of
the evolution of the .NET framework, and they're a core part of LINQ.
I experimented with multicast delegate with the following code, but
got an exception which says: Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.

The code itself seems to be OK. What does this exception really
mean?
Something is very wrong on your machine. It could be the .NET
installation, some bad memory, or something else. The code's fine
though.
BTW, I don't understand how useful multicast delegate can be. It
seems to me that its only purpose is to "simplify" calling multiple
methods with one call. But all methods have to have the same
signature and all of them have to be registered with the given
multicast delegate. Plus, how often does it happen that multiple
methods have the same signature, return void, and need to be called
one after another?
It's very useful for events, to start with. Why should you be limited
to having *one* way of responding to a click, for instance? Multicast
delegates allow for composition of event handlers very neatly.

I've also used them in "Push LNQ" for situations where I've wanted to
compute multiple aggregates from a single input source. I agree that
the uses are relatively limited, but it's still a handy ability.

Jon
Jul 21 '08 #49
On Jul 21, 4:41*am, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
>
Again, code would be helpful. I suspect that when you say "a class
declared in the parent form" you mean "a variable declared in the
parent form" but I don't even know whether you mean "parent" in an
inheritance sense or not.
Jon Skeet--here is the code. I think the problem is much more basic:
I don't know how different forms exist in the namespace. See the
comment at "***" below. I assumed they shared the same classes, but
they don't.

I will wait one or two days and check for an answer here, and, if no
answer, I'll make this a separate thread since it's really not so much
a delegate/event question but a namespace/scope question.

Thanks.

RL

public partial class Form1 : Form
{
Class1 myClass1;

public Form1()
{
InitializeComponent();

myClass1 = new Class1(100, "hello1");

}

public int myForm1Method()
{
// myClass1 seen here
return 1;
}

////////

Public partial class Form2 : Form
{
Class2 myClass2;
Class1 myNewClass1;
public Form2()
{
InitializeComponent();
myClass2 = new Class2();
myNewClass1 = new Class1(99, "helloagain1");

public int myForm2Method()
{
//***myClass2 seen here, myNewClass1 seen here, but 'myClass1' not
seen here. This is true even if Form2:Form1, and if 'public' added to
classes 1, 2. Why is that?

return 2;
}

}

//////////////

//Class1, class 2 are basically the same

class Class1
{

public string str1;
public int interger1;
public Class1()
{
str1 = "hi";
interger1 = 1;

}
public Class1(int i, string s)
{
str1 = s;
interger1 = i;
}

}
}
//

Jul 21 '08 #50

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.