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

R

raylopez99

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.


It's not. But if you mean the <T> part, that's generics - which is a
whole other topic.

No, I meant the keyword 'Action', but it's off topic.

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

Jon Skeet [C# MVP]

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

Author

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);
}
}
}
 
R

raylopez99

Hi Author--I'm not really qualified to answer completely, as I'm still
learning, but here's my two cents.

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?

Yes, this seems to be the case. Also if you do a "publisher -
subscriber" model, where you can fire the publisher at one part of
your class, and all subscribers that are listening will respond in the
rest of your code, kind of like a global, multicast "GOTO" (in my
mind's eye). But, you can also do the same thing simply by
judiciously calling other 'subscribing' methods from inside the method
that is 'publishing', and achieve the same thing, so to a degree it's
syntatic sugar or eye candy. Actually I find it more confusing, but
maybe because I'm still new to the delegates thing. Getting the hang
of it though.
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.

I had no problems compiling and running this code. To speed up the
program, I commented out the part where you have to hit a key, //
Console.ReadKey, and got this output, as expected:
M1: Just a test.
M2: Just a test.
Press any key to continue . . .

To see that M2 is being executed you can switch the order of +s1 and
+s2, to get "M2: a test. Just", as you would expect.
The code itself seems to be OK. What does this exception really
mean?

Nothing. I think you have a hardware problem. Check you physical
memory with one of these memory stress test programs you can get free
on the web.
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?

Well, the .NET framework uses these all the time. Seems C#
programmers like to even make your 'custom' method inhereit
from :EventArgs, so you might have a custom class--

public class MyCustomClass: EventArgs
{
// stuff here
}

Then, in another class in the same 'scope' / namespace,

pubic class SecondClass
{

public event EventHandler <MyCustomClass> MyEventHandler; //note
MyCustomClass is a derived class from EventHandler, so this is OK

//and, my book says the 'convention' is to write a protected virtual
method that fires this event, prefixed with the word 'On', and then
accept a single EventArgs argument like so:

protected virtual void OnMyEventHandler (MyCustomClass e) // 'e' is
conventionally used to designate a class that's of type EventArgs
{
if (MyEventHandler != null) //always check to see eventhandler is not
null, or exception thrown
{ MyEventHandler(this, e);}

//
}

//then you have a method with signature "object, EventArgs" like so,
somewhere in one of your classes within the same namespace scope:

static void AMethodHere (object sender, MyCustomClass e)
{
// do stuff with 'e', which carries the information, while object
sender is almost always, from the examples I've seen, the 'this'
reference

}

To fire this Event, you use this convention:

SecondClass.MyEventHandler += AMethodHere; // this is known as
"registration", and you can also use this older format:
SecondClass.MyEventHandler += new EventHandler(AMethodHere);

//then, you 'fire' after registration like this:

MyCustomClass myCustomClass1 = new MyCustomClass;

MyEventHandler(this,myCustomClass1); //usually this is called inside
another class, hence 'this' //this is the firing

or, you can use the "On" method above like so;

OnMyEventHandler(myCustomClass); //which fires it the same way, but
checks first for null pointer


Sorry if this was confusing, you just have to see a lot of examples
before you get it. The format changes slightly but the underlying
stuff is largely the same.

RL
 
J

Jon Skeet [C# MVP]

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
 
R

raylopez99

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;
}

}
}
//
 
B

Bill Woodruff

forgive me if i sound like a voyeur here :), but i really enjoyed reading
this thread, and got many useful pointers for further study from it.

i found myself feeding the stray thought (they're often yowling in the back
alleys of my mind, those strays) that there might be a place for a neologism
:

algorighteousness

which would describe : "a state of inner conviction that a certain technical
strategem embodies a profound truth equal in importance to life itself with
an inherent tendency for the level of conviction to become more intense as
said strategem is debated."

the stray thought that made me think of this thread as the libretto of an
opera : i didn't feed.

regards, Bill
 
A

Author

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

Thank you.

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.

I think the frustration comes from not understanding

what are the stuffs which the invoking method knows vs. what are the
stuffs which the invoking method does not know.

So, for example, in the following code,

Button b = new Button();
b.Text = "Click me";
b.Click += new System.EventHandler(b_Click);

we dynamically create a button control, and delegate its Click event
handler to b_Click method through newing System.EventHandler. Does
this mean that

1. we want the Click event of the button to be handled,
2. we don't know how it is gonna be handled,
3. if we know how the Click event should / will be handled, then we
simply code the logic at where "new System.EventHandler(b_Click)" is,
maybe through an anonymous method

?

Not sure if I am close.
 
A

Author

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.



Something is very wrong on your machine. It could be the .NET
installation, some bad memory, or something else. The code's fine
though.


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

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?
 
A

Author

[...]
I think the frustration comes from not understanding
what are the stuffs which the invoking method knows vs. what are the
stuffs which the invoking method does not know.

I feel your pain.  To some extent, it's a matter of experience.  You don't  
say how much programming experience you have, but in the simplest systems,  
this just doesn't come up at all.  But in more real-world situations, and  
especially in object-oriented programming, you start seeing code that  
depends on some implementation detail being done at some later time and/or  
by someone else.

If people don't use their real names in this group, you can get an
idea about their programming experience. :)

The only real-world experience I've had with delegates is in event
handling. I have a little practice encapsulating methods with
delegates, but those use delegate for delegate's sake and don't help
me learn when, besides event handling, in the real world, I should use
a delegate.

There's more, scroll down please.
Virtual functions are an example of this, as are interfaces and abstract  
classes (two closely related concepts, which to some extent rely on the  
concept of virtual functions).  Function pointers are yet another, and  
delegates are the C# form of function pointers.  These all allow someone  
to write some code A that calls an implementation B that is, at the time  
that the code A is being written, does not exist or is otherwise unknown.

Until you've seen some actual examples (MSDN has a number of them, which  
you should be able to find by searching on terms and examples used in this  
thread), it can indeed be hard to really comprehend the use.  Once you've  
seen the examples and especially once you've been able to use the  
techniques yourself, they start to make more sense.





No.  That is, yes...you could write an anonymous method.  But at the point  
you suggest, you would still be taking advantage of the polymorphic  
behavior of the delegate.

Thanks. Yes, in an environment where the b_Click event handler is
developed by a different developer, this event delegate makes good
sense to me. It seems that you implied that if I *do* know how the
Click event will be handled, I can code the logic on the right hand
side of b.Click += through a anonymous method block.
 
J

Jon Skeet [C# MVP]

raylopez99 said:
Jon Skeet--here is the code.

Well, that's part of the code. You've not included the designer files,
which contain InitializeComponent. This is why I usually use console
apps for examples - they're much simpler. The principles are the same
though.
I think the problem is much more basic:
I don't know how different forms exist in the namespace.

Well, that's *one* problem - but it's not the reason for the compiler
complaining. The forms are just classes like Class1 and class2.
See the comment at "***" below. I assumed they shared the same
classes, but they don't.

That depends on what you mean by "shared".
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.

Have I ever taken two days to answer you? :)

The reason your code didn't compile was that the variable was private
in the base class. Here's a short but complete example demonstrating
it, without involving a GUI or any more classes than we really need.

using System;

class Base
{
private string privateBaseField = "1";
public string publicBaseField = "2";
}

class Derived : Base
{
private string privateDerivedField = "3";
private string publicDerivedField = "4";

public void Foo()
{
// Illegal
// string a = privateBaseField;
string b = publicBaseField;
string c = privateDerivedField;
string d = publicDerivedField;
}

// Just keep the compiler happy for a console app
static void Main() {}
}

Now, running this program won't actually do anything, but look inside
the Foo method. It has access to privateDerivedField because that's
declared in the same class as Foo - but it *doesn't* have access to
privateBaseField because that's declared in Base. It has access to both
publicDerivedField and publicBaseField because they're public.

There are various other access modifiers - look them up in Nutshell for
the details.

Does that help?
 
J

Jon Skeet [C# MVP]

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<T> ourselves. 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<T> delegate is for. Here's the signature:

public delegate bool Predicate<T>(T obj)

So, any instance of Predicate<T> is 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<T> predicate)
{
// "this" is the list
foreach (T element in this)
{
// Test the current element against the predicate
if (predicate(element)
{
// 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.Collections.Generic;

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

static void Main()
{
List<string> list = new List<string>(Names);

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

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

// C# 3 syntax - lambda expression
string endsWithY = list.Find(x => x.EndsWith("y"));


Console.WriteLine(fourLetters);
Console.WriteLine(beginsWithA);
Console.WriteLine(endsWithY);
}

static bool MatchFourLetters(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/Chapter5/Closures.aspx
 
J

Jon Skeet [C# MVP]

Author said:
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?

They could come from completely different pieces of code which don't
know about each other. One piece of code might be capturing all events
to send back to the user experience team, another piece of code might
be actually acting on the button click (e.g. to save a document).
 
R

raylopez99

Does that help?

-

No. It doesn't work. What is going on is more complicated than that,
unfortunately, but thanks for trying. What you need is a forward
reference outside the class normal constructor, but even then you
cannot access the Form1's classes. 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).

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.

RL



public partial class Form1 : Form
{
Class1 myClass1; /*!*/ //THIS IS KNOWN AS A FORWARD REFERENCE
IN C++, AND IT ALLOWS YOU TO 'SEE' CLASS1 in the Normal constructor
below, but that''s just PART of the problem. The other problem is you
CANNOT, no matter what, 'see' any such instantiated class in Form 2
which is a child of main form, Form 1--RL

public Form1()
{
InitializeComponent();
myClass1 = new Class1(100, "hello1"); /*!*/ //BUT FOR THE
FORWARD REFERENCE ABOVE, YOU CANNOT EVEN INSTANTIATE HERE...BUT AGAIN,
THAT'S JUST HALF THE PROBLEM.
}
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 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;
}

}
//////////////
//Class1, class 2 are basically the same //deleted.


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

Ray
 
R

raylopez99

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
 
J

Jon Skeet [C# MVP]

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

Jon Skeet [C# MVP]

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

Jon Skeet [C# MVP]

Just rereading your code - look closely:
////////
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 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.
 
P

Pavel Minaev

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.TextChanged
handler, and update the textbox from the TreeView.AfterLabelEdit 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.
 
A

Author

Jon said:
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<T> ourselves. 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<T> delegate is for. Here's the signature:

public delegate bool Predicate<T>(T obj)

So, any instance of Predicate<T> is 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<T> predicate)
{
// "this" is the list
foreach (T element in this)
{
// Test the current element against the predicate
if (predicate(element)
{
// 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.Collections.Generic;

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

static void Main()
{
List<string> list = new List<string>(Names);

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

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

// C# 3 syntax - lambda expression
string endsWithY = list.Find(x => x.EndsWith("y"));


Console.WriteLine(fourLetters);
Console.WriteLine(beginsWithA);
Console.WriteLine(endsWithY);
}

static bool MatchFourLetters(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/Chapter5/Closures.aspx

--
Jon Skeet - <[email protected]>
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.
 

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