473,765 Members | 1,967 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 "UnAwareCla ss"
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.Collecti ons.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.WriteLi ne("...now for external use of delegates from two
classes...");

DelegateClass.P ublicHigherPowe r2 sQr = new
DelegateClass.P ublicHigherPowe r2(UnAwareClass .Square); //!!! Note: how
called: UnAwareClass.Sq uare

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

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

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

DelegateClass.P ublicHigherPowe r2 Cub2 = new
DelegateClass.P ublicHigherPowe r2(UnAwareClass .Cuber);

//!!! note: how called: UnAwareClass.Cu ber

ji2 = myDelegateClass .DoOp(Cub2, 11);

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

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

}
}
}
////////////
using System;
using System.Collecti ons.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 PublicHigherPow er2(int x); //delegate to
be used externally (keyword delegate must of course be declared here)

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

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

}
Jul 13 '08
69 5590
On Jul 21, 12:08*pm, raylopez99 <raylope...@yah oo.comwrote:
>
Again, a simple example where you can, using simple Windows forms,
'see' a class declared in a parent base form in the form that is a
child, would be helpful. *I don't think I played with the "Properties "
to make this impossible, but, if you've seen this problem before
(playing with the properties will make a child form 'private' and/or
parent form 'private' so nothing can be 'seen' by any other form),
please let me know.

Thanks, gotta run...

OK, back again. I was thinking about this over dinner, and concluded
that the solution lies with passing information by way of a
parametricized constructor rather than a default normal constructor.

And sure enough that worked.

Simple example: if you want to pass class1 from the parent form to
the child form, you do this, from inside of Form1 (the parent form):

Form2 frm2 = new Form2(myClass1) ;
frm2.Show();

// you do not do this:

//won't work
// Form2 frm2 = new Form2(); //normal, unparametized constructor will
not work
// frm2.Show();

That simple..now Class1 myClass1 is 'seen' in Form2, no problem.

I'll post on a separate thread, and reserve the right to make fun of
you, Jon Skeet, for not catching such an obvious thing. What KIND of
a C# programmer are you? Just kidding...I'll keep the sarcasm to a
minimum, but, honestly (not really) what were you thinking Jon Skeet?

RL
Jul 21 '08 #61
raylopez99 <ra********@yah oo.comwrote:
Does that help?

No. It doesn't work. What is going on is more complicated than that,
unfortunately, but thanks for trying.
Actually the problem is *exactly* the one I showed in the code sample.
You're making it more complicated by involving partial classes, forms,
and Class1/Class2, but the core of the problem is the same thing:
you're trying to access a private variable in a base class from a
derived class, and you just can't do that.
What you need is a forward
reference outside the class normal constructor, but even then you
cannot access the Form1's classes.
There's no such thing as a forward reference in C#.

What you've labeled as a forward reference in your sample source code
is actually declaring a variable.
Something must be going on behind
the scenes depending on how the rest of the 'partial class' works.
Try this in Forms GUI, not console mode,and perhaps you'll see. I
have nothing against what you say in theory--but that's not the way
these forms are working (non-console mode).

I reproduce below and emphasize what I'm talking about with the
symbol /*!*/. BTW I made all the classes public, all the members
public (so they are working effectively as structures and you still
cannot 'see', using the InteliSense tool, the classes in the other
form).
No, you haven't made all the members public:

public partial class Form1 : Form
{
Class1 myClass1;

That's declared a *private* variable.

If you change it to:

public partial class Form1 : Form
{
public Class1 myClass1;

then you'll be able to see it where you were complaining.
Here's a quick tip (cause I have to go now)...try this yourself and
just see if you can reference, from a child form, a class declared in
the parent.
Once again, you don't declare a *class* in the parent (leaving nested
types aside). You declare a *variable* in the parent. That's what
you've done in the code quoted above, but you've declared it as a
private variable. That means the child classes can't access it.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 21 '08 #62
raylopez99 <ra********@yah oo.comwrote:
OK, back again. I was thinking about this over dinner, and concluded
that the solution lies with passing information by way of a
parametricized constructor rather than a default normal constructor.
No, it's got nothing to do with that. You may have come up with a
workaround, but if you still don't understand what was going on you're
going to be twisting your code all over the place for no reason.
And sure enough that worked.

Simple example: if you want to pass class1 from the parent form to
the child form, you do this, from inside of Form1 (the parent form):

Form2 frm2 = new Form2(myClass1) ;
frm2.Show();

// you do not do this:

//won't work
// Form2 frm2 = new Form2(); //normal, unparametized constructor will
not work
// frm2.Show();

That simple..now Class1 myClass1 is 'seen' in Form2, no problem.
Not if you're still trying to refer to a *private* myClass1 variable
from a different class.
I'll post on a separate thread, and reserve the right to make fun of
you, Jon Skeet, for not catching such an obvious thing. What KIND of
a C# programmer are you? Just kidding...I'll keep the sarcasm to a
minimum, but, honestly (not really) what were you thinking Jon Skeet?
I was thinking, and I'm *still* thinking, that you don't really
understand the problem properly.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 21 '08 #63
raylopez99 <ra********@yah oo.comwrote:

Just rereading your code - look closely:
////////
Public partial class Form2 : Form
{
Class2 myClass2;
Class1 myNewClass1;
public Form2()
{
InitializeCompo nent();
myClass2 = new Class2();
myNewClass1 = new Class1(99, "helloagain 1");
public int myForm2Method()
{
//***myClass2 seen here, myNewClass1 seen here, but 'myClass1' not
seen here.

*/!*/ // THIS IS KEY. READ THE ABOVE COMMENT. YOU CANNOT SEE
myClass1 in this form, child form Form2. EVEN IF YOU CHANGE it to
"Public partial class Form2 : Form1" //<--NOTE THE INHEREITANCE HAS
CHANGED.
//This is true even if Form2:Form1, and if 'public' added to
classes 1, 2. Why is that?
return 2;
}
That code is trying to declare a method inside the constructor. I
strongly suspect that *isn't* the code you had. I really hope it isn't,
anyway.

Once again, if you could post *complete* code (i.e. avoid partial
classes and forms - they really are irrelevant to your problem) you
would make your life a lot easier.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 21 '08 #64
On Jul 21, 9:46*pm, Author <gnewsgr...@gma il.comwrote:
OK, thanks. *I have also suspected that I may have some hardware
problem with my memory, because when I googled, I could not find a
whole lot info about this exception. *Now back to multicast delegate.
When there are more than one ways to respond to a button click, why
can't we just put those ways in a single click event handler?
Mostly because those "ways" might not even know about each other. This
becomes obvious really soon if you do GUI programming using the
Observer pattern - i.e., you don't just have event handlers subscribed
to buttons etc to handle user input, but you also have event handlers
subscribed to PropertyChanged event (or similar) on your business
object to dynamically update GUI as model changes.

If it's still unclear, that's alright. I can actually explain it on a
real-world example. Consider a GUI application which edits a tree of
objects. On the left of it is the actual TreeView control that
displays the hierarchy; labels represent Name property of the objects
in the tree. On the right is a panel which has different content
depending on the kind of the element currently selected in the tree,
but which usually includes a textbox to edit Name. The user can also
edit names directly in the tree, by click-pause-click as it usually
works in Windows. And, of course, we want the tree and the textbox to
stay in sync always - if one is updated, so should be the other.

Now, you can, of course, update the tree from the TextBox.TextCha nged
handler, and update the textbox from the TreeView.AfterL abelEdit event
handler. But, as more and more controls that should stay in sync are
added, the more code you have to add to all handlers, and the more
entwined logically different parts of your application become (in the
real-world program, there was also a preview window that had to be
refreshed, and "Save" button on the toolbar that tracked changes to
enable/disable itself depending on whether there was anything to
save).

On the other hand, a much simpler approach is to let every distinct
part just change the business object on user input, without concerning
itself about propagating changes to the rest of UI. To do the latter,
every control that needs to be aware of the changes subscribes to
PropertyChanged event of the business object. Note that in this
scenario, we have several event handlers on the same event of the same
object which do not know anything about each other (nor should they,
really) - all components are truly separate, and can be reused and
refactored each on its own. Yet the end result is a complex system
working in unison - as user inputs text in the textbox, the Name
property of the object is updated, which causes PropertyChange event,
which in turn updates the tree, the toolbar, the preview window, and
the rest of it. And furthermore, adding a new change-aware control
does not require you to change the code for any existing ones.
Jul 21 '08 #65
Jon Skeet [ C# MVP ] wrote:
Author <gn********@gma il.comwrote:

<snip>
I struggle to understand "code that wants to be able to execute some
arbitrary code without knowing what that code is at compile time".

Marc also says in the 2nd post of this thread that "Delegates become
useful when the code that invokes them cannot possibly know about the
actual methods (such as List<T>.Find)", which, too, I struggle to
understand.

<snip>

It does take a while to really grok it, but it's important stuff -
particularly for LINQ. I'll explain it using List<T>.Find as an
example, as then we don't need to include any events, which complicate
things a bit.

Let's suppose we were implementing List<Tourselves . We want to write
the Find method, which is going to find an element. What element is it
going to find though? Well, we could take a parameter of type T, and
then call Equals on each element in the list to see if it's the same as
the one being passed in. That's not really useful though. What would be
more useful would be to be able to pass something else which somehow
specified what we wanted to find - something which could look at each
element and say whether or not it was the right one. That's exactly
what the Predicate<Tdele gate is for. Here's the signature:

public delegate bool Predicate<T>(T obj)

So, any instance of Predicate<Tis some code which can take an object
of type T, and return a Boolean when it's finished processing, to say
whether or not it "matches" the delegate.

With that in place, List<T>.Find is simple. All we need to do is loop
through all the elements, call the specified predicate on each element,
and if it returns true, return that element. If none of them do, we'll
return the default value for T. Here's an example implementation:

public void Find(Predicate< Tpredicate)
{
// "this" is the list
foreach (T element in this)
{
// Test the current element against the predicate
if (predicate(elem ent)
{
// Success! Return the element
return element;
}
}

// Didn't match anything.
return default(T);
}

So, that's the side which will call the predicate. Now we've got to
provide the predicate when we call Find. C# 2 and 3 make this a lot
easier, as shown here:

using System;
using System.Collecti ons.Generic;

class Test
{
static readonly string[] Names =
{"Jon", "Pete", "Ray", "Author", "Bill", "Marc"};

static void Main()
{
List<stringlist = new List<string>(Na mes);

// C# 1 syntax (apart from generics!)
string fourLetters = list.Find
(new Predicate<strin g>(MatchFourLet ters));

// C# 2 syntax - anonymous method
string beginsWithA = list.Find(deleg ate(string x)
{ return x.StartsWith("A "); }
);

// C# 3 syntax - lambda expression
string endsWithY = list.Find(x =x.EndsWith("y" ));
Console.WriteLi ne(fourLetters) ;
Console.WriteLi ne(beginsWithA) ;
Console.WriteLi ne(endsWithY);
}

static bool MatchFourLetter s(string text)
{
return text.Length == 4;
}
}

Notice how the "searching" part is implemented in List<T>, but the
"what to search for" part is specified in the test code - and it's very
flexible, as we've shown here.

Here's another look at the same kind of thing:
http://csharpindepth.com/Articles/Ch.../Closures.aspx

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Thank you very much. I think this Find example is enlightening. Most
of the time, we see delegate examples that are related to event
handling or they are for delegate's sake, giving us a false impression
that delegates are for event handling only.

I think the delegate philosophy seems to be clear now: We use a
delegate

1. when we don't know or it is impossible for us to know how a
certain part of an application is to be implemented, or

2. we know of a bunch of different potential ways to approach it, but
instead of trying to implement all possibilities and cluttering our
code with switches or ifs and maybe additional argument into the
method signature, we give (hence delegate) the concrete task to the
consumer class.
Jul 22 '08 #66
raylopez99 <ra********@yah oo.comwrote:
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've just spotted something I hadn't seen before, which makes my sample
code somewhat less useful. You'd said that Form2 derived from Form1 -
but in your code, they both just derive from Form.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 22 '08 #67
Author <gn********@gma il.comwrote:
Thank you very much. I think this Find example is enlightening. Most
of the time, we see delegate examples that are related to event
handling or they are for delegate's sake, giving us a false impression
that delegates are for event handling only.
Not only that, but people also get confused as to what an event
actually is. It's just a pair of methods - add and remove - linked by
some metadata.
I think the delegate philosophy seems to be clear now: We use a
delegate

1. when we don't know or it is impossible for us to know how a
certain part of an application is to be implemented, or

2. we know of a bunch of different potential ways to approach it, but
instead of trying to implement all possibilities and cluttering our
code with switches or ifs and maybe additional argument into the
method signature, we give (hence delegate) the concrete task to the
consumer class.
Yup. And of course 2 is just a special case of 1, really.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 22 '08 #68
On Jul 22, 1:19*am, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
Author <gnewsgr...@gma il.comwrote:
Thank you very much. *I think this Find example is enlightening. Most
of the time, we see delegate examples that are related to event
handling or they are for delegate's sake, giving us a false impression
that delegates are for event handling only.

Not only that, but people also get confused as to what an event
actually is. It's just a pair of methods - add and remove - linked by
some metadata.
I think the delegate philosophy seems to be clear now: *We use a
delegate
1. *when we don't know or it is *impossible for us to know how a
certain part of an application is to be implemented, or
2. we know of a bunch of different potential ways to approach it, but
instead of trying to implement all possibilities and cluttering our
code with switches or ifs and maybe additional argument into the
method signature, we give (hence delegate) the concrete task to the
consumer class.

Yup. And of course 2 is just a special case of 1, really.
That's right, I thought about this, too. Actually thought about making
this point. As a matter a fact, event handling is also only a special
case of delegate usage.
>
--
Jon Skeet - <sk...@pobox.co m>
Web site:http://www.pobox.com/~skeet*
Blog:http://www.msmvps.com/jon.skeet
C# in Depth:http://csharpindepth.com
Jul 22 '08 #69
Author <gn********@gma il.comwrote:
Yup. And of course 2 is just a special case of 1, really.

That's right, I thought about this, too. Actually thought about making
this point. As a matter a fact, event handling is also only a special
case of delegate usage.
Absolutely. Open your mind to the possibilities of doing other things
:)

It sounds like you've got a *much* better handle on delegates now.

--
Jon Skeet - <sk***@pobox.co m>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 22 '08 #70

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

Similar topics

4
3238
by: Phil G. | last post by:
I was recently struggling to adapt an example I have using delegate methods, IasynResult and AsynCallback. Doing a little research I came across an example, which in fact was being used to return data from an external sql database...exactly what I am doing. This example used the System.Threading namespace and thread.start etc What are the pro's and con's of using/choosing either option? They both 'appear' to create a process on a new...
12
206
by: tshad | last post by:
I have a set up javascript functions that pass function pointers and I am trying to figure out how to do the same thing in C# using delegates. // We define some simple functions here function add(x,y) {return x + y;} function subtract(x,y) {return x - 1; } function multiply(x,y) {return x * 1; }
0
9568
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9398
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9832
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7378
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5275
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5421
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3924
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3531
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2805
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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

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