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

R

raylopez99

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.Square); //!!! 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.Cuber);

//!!! 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);
}
}

}
 
M

Marc Gravell

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,int> that can be used in place of declaring your own.

Just some pointers... [no pun intended]

Marc
 
R

raylopez99

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,int> that 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
 
P

Pavel Minaev

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.
 
R

raylopez99

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
 
R

raylopez99

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.Square); //!!! 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.Cuber); //long way - 2
lines instead of one

DelegateClass.PublicHigherPower2 RetINT;
RetINT = new
DelegateClass.PublicHigherPower2(myUnAwareClass.returnINT);

DelegateClass.PublicHigherPower2 RetINT2 = new
DelegateClass.PublicHigherPower2(myUnAwareClass.returnINT); //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.Cuber);
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);
}
}
}


////////////
 
J

Jon Skeet [C# MVP]

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
 
R

raylopez99

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
 
J

Jon Skeet [C# MVP]

raylopez99 said:
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.
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.
 
R

raylopez99

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.

You could have stopped Pete wholely at "[t]he compiler version isn't
the issue here", but you opened the door for flaming by continuing
with "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/library/aa288459(VS.71).aspx

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

First, you'll note that though legal, and though it will compile, the
MSFT example does not use a properly (from a stylistic point of view)
constructed composite class between the public structure Book and the
class public class BookDB. Instead, it creates a new Book structure
inside the ArrayList member "list". Specifically: // Add a book
to the database:
public void AddBook(string title, string author, decimal price,
bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}

IMO this is bad form. Instead AddBook should have passed a instance
of the public structure Book instead of creating it inside a
ArrayList. I know I'll get some flack for this, but I've seen how
doing this down the road can lead to problems during instantiation
when inherietance is involved. Sorry, I can't be more specific.

Second, it doesn't show how, as in my example, the code for the
delegate can be in a class outside the class the delegate is called in
(here, the delegate is a variable declared outside of *any* class, but
in the same namespace of course). While it's a small point (arguably
the Microsoft example is more comprehensive since is shows the
delegate can 'live' outside a class, kind of like the use of a static
int counter), it's still a point.

Third, the main point of the example (IMO), is the clever traversal of
a list and the use of a delegate to do, ala a 'functor' in C++,
something to the list. THis is the cleverest part of the program:

// Call a passed-in delegate on each paperback book to process
it:
public void ProcessPaperbackBooks(ProcessBookDelegate
processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
// Calling the delegate:
processBook(b);
}

when used with these two lines:

bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle)); and
bookDB.ProcessPaperbackBooks(new
ProcessBookDelegate(totaller.AddBookToTotal));

Thus, the "foreach" method is traversing a list and 'doing something'
but different somethings, when the 'somethings' (methods) have the
same signature of the delegate, namely "public delegate void
ProcessBookDelegate(Book book);", which means the something (methods)
must take a parameter 'Book' and return 'void' . Nice and
educational. So delegates are like interfaces for common methods, as
pointed out in the comments.

Fourth, the program does not show how you can use .Invoke to call a
delegate (but it is discussed in the commentary), nor does it use my
example's delegate involking function of " public int
DoOp(PublicHigherPower2 ar, int x) //note format
{ return ar(x); }. A small point, but worth
noting.

Fifth, the program does not demonstrate the "inline" way of using a
delegate, as I refered to in my "NewStyle" delegate.

All in all, the MSFT example is clever, but different from my
program. Nevertheless I liked it so much I've copied and pasted in
into my library of examples. Thanks.
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.

Not true. And by your own admission it's "missing" something. What?
The reader is left uneasily wondering.
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,  
int> instead

A point already made in this thread. Generic template type
declarations are not my forte, they don't make sense to me but I see
your point.

     -- 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).

That's true. But when I wrote the name I wasn't thinking far enough
ahead. Small point, as I can always do a global search and replace of
this term.
     -- 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.

Not true. Not distracting but innervating. And a small point.
     -- 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).

This is not true. "public delegate int PublicHigherPower2(int x); "
DOES in fact 'live inside' (has a composite member) of class
myDelegateClass. It doesn't inhereit, but it's a member. Anyway,
regardless, a small point.
     -- 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?  Inwhat  
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.

It was interesting to me, since, as I pointed out, in past examples
the delegates "lived" (were members of) both classes. Here,
"UnAwareClass" does not have a delegate member inside it.
     -- 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?

Exactly. There were NO ill effects. That's what's being noted,
exactly. Why ask why?
     -- 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).

OK, OK. It was news to me, see above. We all learn something for the
first time, right? Unless you're born 'sua sponte' with all the
conventions of C# inside your head, like the goddess Athena sprung
fully formed from the forehead of Zeus. That would be you.
     -- 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.

Not true. I was demonstrating various aspects of traversal. In
another example (which I didn't post, but I can), I even created an
array of delegates that can be filled with delegates, so that you have
more flexibility (note in my example CombinedDelegates01, the combined
delegate can only take one parameter value at a time, which
'propagates' through the whole invocation list, whereas if you set up
an array of delegates (of the same type of course) each delegate can
potentially take a different value of parameters, then you can
traverse the array to invoke each of these 'distinct' delegates).

     -- 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.

No, I was showing how there's no "power of" (^) operator in C#, as
there is in other languages. A bug IMO.
     -- 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.

I like 'foreach' since it worked fine. I thought I'd have to use
IEnumerator interface for a while, which I hate using since it's so
clunky looking.
     -- The comment "One advantage of delegates over Events is thata  
delegate can return a value directly" is simply false.  An event can use  
any delegate type, including one that returns a value.

Not what my textbook says, but maybe it's an old version. My textbook
says Events can only return void. Let me see if I can find the exact
quote...I can't find it, but I have a handwritten note that says 'by
convention, event delegates return void'. So perhaps I was thinking
of the convention, in which case this is news to me. But I need
confirmation of this...a quick GOogle is in order...AHA! LIAR LIAR
PACIFIER! "Event Handlers in the .NET Framework return void and take
two parameters..." says the web. So, at least in the .NET OOP API,
events *do* all return void.
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.
Thanks.

 I still prefer  
the actual MSDN documentation though.  

To each their own. I prefer code I wrote since I understand it
better.
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.

Static inheritance? I don't recall that...a quick Google found
nothing with me in it. I have in the past claimed the concept of
inheritance is usually rare, except for polymorphic runtime casting,
but that's another matter.

Thanks for your input.

RL
 
R

raylopez99

On Jul 13, 5:03 pm, "Peter Duniho" <[email protected]>
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
 
J

Jon Skeet [C# MVP]

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
 
R

raylopez99

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
 
J

Jon Skeet [C# MVP]

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/Chapter5/Closures.aspx

Jon
 
B

Ben Voigt [C++ MVP]

As for specific comments regarding your example, I'll start by pointing
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."
 
R

raylopez99

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.
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).
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?
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
 
R

raylopez99

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.
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.
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.
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.
I wasn't ambiguous.  You simply failed to read (or comprehend) all the  
words.

Or so it seems (in your mind's eye).

RL
 
P

Pavel Minaev

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.
 
B

Ben Voigt [C++ MVP]

As far as I know, a C++ function pointer cannot encapsulate the
Simply that there's a variant of function pointers, the pointer-to-member
function pointer, which is designed solely for use with objects.
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.
 
B

Ben Voigt [C++ MVP]

By the way, if you're going to try to ride on Ben's coat-tails, you
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.
 

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