473,714 Members | 2,598 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How to pass information, classes between forms in Windows Applicationmode


Keywords: scope resolution, passing classes between parent and child
forms, parameter constructor method, normal constructor, default
constructor, forward reference, sharing classes between forms.

Here is a newbie mistake that I found myself doing (as a newbie), and
that even a master programmer, the guru of this forum, Jon Skeet,
missed! (He knows this I'm sure, but just didn't think this was my
problem; LOL, I am needling him)

If you want to pass information between two forms comprised of
classes, whether or not they are parent/child, modal or modeless,
dialog or non-dialog you have to use the non-normal/ non-default or
parametricized or parameter constructor, not a default (no parameter)
normal constructor. Explanation below.

Let's say you have a button on your form that you click to bring up
another form, and the button has an Events handler called
"clikMeButton2B ringUpANew_Chil d_Form_to_The_M ainForm_Click".

Let's say in Designer mode you've already built a nice new (child or
second or dependent or non-main) form called "Form2" (I think you can
also programmically 'build' a new form, but I like using the Designer
mode, drag-and-drop and let the Wizard figure out how to initialize
the form, but I digress).

Let's say you have a class, called Class1, that you declared in your
first form, during instantiation of that form, having an instance
"myClass1", and now you want that same class instantiation to be
passed to the Form2. How to do that? If you use the wrong
constructor it won't be 'seen' by the new form. Hence you must do
this:

private void
clikMeButton2Br ingUpANew_Child _Form_to_The_Ma inForm_Click(ob ject
sender, EventArgs e)
{
// Form2 frm2 = new Form2(); //Do not do this--it won't
work! You cannot see myClass1 in frm2

Form2 frm2 = new Form2(myClass1) ; // this will work;
myClass1 will be seen in Form2
// of course, we assume you do have a parameter constructor in Form2
that accepts class1 as a parameter, ie., you have a constructor with
this signature in Form2 (Class1 C1) {};//see further below at (#1)

frm2.Show(); //shows the form, etc
}

That's it. Done. You can also pass more than one class of course,
with the proper signature.

(#1) And just to make the point clearer, Form2 must have as a
constructor something besides the normal (default) non parameter
constructor, along these lines:

public Form2(Class1 passClass1_from _Form1)
{
myClass2_that_e xists_in_Form2 = passClass1_from _Form1; //
names are arbitrary of course

InitializeCompo nent();

// other stuff here if you want
}

Done.

One more thing as an aside, and it has nothing to do with the above:
you need, in Form 1, to be careful where you put class1; it has to be
sort of like C++, and placed as a 'forward reference' before Form1 is
constructed, along these lines:

public partial class Form1 : Form
{
Class1 myClass1; //Note where this is located! outside the
default constructor for Form1
// this is called a 'forward reference' in C++, and you need to do
this for C# as well
public Form1()
{
InitializeCompo nent(); //mandatory for all forms, stuff
that the Wizard fills and I don't fool with

myClass1 = new Class1();
//or, if your Class1 takes parameters int i, string s, myclass1=new
Class (10, "hi");

//other stuff here, like, for example, this.AutoValida te =
AutoValidate.En ableAllowFocusC hange; //etc

}

/// other stuff here

}

The point being: you need a forward reference if the Class1 is not
'nested' in the Form1 {}, that is, if Class1 is part of a separate
translation unit or module, even if Class1 is in the same namespace as
Form1.

RL
Jul 21 '08 #1
12 11097
raylopez99 <ra********@yah oo.comwrote:
Keywords: scope resolution, passing classes between parent and child
forms, parameter constructor method, normal constructor, default
constructor, forward reference, sharing classes between forms.

Here is a newbie mistake that I found myself doing (as a newbie), and
that even a master programmer, the guru of this forum, Jon Skeet,
missed! (He knows this I'm sure, but just didn't think this was my
problem; LOL, I am needling him)
I still don't think it's your problem. You're still confused - and
what's more you've changed the problem from "accessing a variable" to
"informatio n passing".
If you want to pass information between two forms comprised of
classes, whether or not they are parent/child, modal or modeless,
dialog or non-dialog you have to use the non-normal/ non-default or
parametricized or parameter constructor, not a default (no parameter)
normal constructor. Explanation below.
Certainly if you want to pass information from one context to a new
object, using a parameterised constructor is the way to go. That has
nothing to do with being able to access another type's variables
though.

Just passing a parameter doesn't mean that Form2 is magically able to
see Form1.myClass1. Form2's constructor will be able to see the
parameter, which starts off with the same value as Form1.myClass1, but
you can't actually refer to the Form1.myClass1 variable from Form2.

<snip>
The point being: you need a forward reference if the Class1 is not
'nested' in the Form1 {}, that is, if Class1 is part of a separate
translation unit or module, even if Class1 is in the same namespace as
Form1.
No. There is no such thing as a forward reference in C#, and what you
seem to think is a forward reference is actually just a variable
declaration.

--
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 #2
On Jul 21, 1:34*pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
raylopez99 <raylope...@yah oo.comwrote:
Keywords: scope resolution, passing classes between parent and child
forms, parameter constructor method, normal constructor, default
constructor, forward reference, sharing classes between forms.
Here is a newbie mistake that I found myself doing (as a newbie), and
that even a master programmer, the guru of this forum, Jon Skeet,
missed! (He knows this I'm sure, but just didn't think this was my
problem; LOL, I am needling him)

I still don't think it's your problem. You're still confused - and
what's more you've changed the problem from "accessing a variable" to
"informatio n passing".
Nope. That was my problem. My problem was that I could not even see
the class1 in Form2 and now it's solved. Your problem (in your mind's
eye) is another problem altogether.

Certainly if you want to pass information from one context to a new
object, using a parameterised constructor is the way to go. That has
nothing to do with being able to access another type's variables
though.
Certainly.

And accessing another type's variables has nothing to do with my
problem, whether you acknowledge it or not. BTW, all my variables
were set public and still the code did not work until I hit upon the
parameterised constructor.
>
Just passing a parameter doesn't mean that Form2 is magically able to
see Form1.myClass1. Form2's constructor will be able to see the
parameter, which starts off with the same value as Form1.myClass1, but
you can't actually refer to the Form1.myClass1 variable from Form2.
You can too. Using the public properties Get and Set, you certainly
can refer to the Form1.myClass1 variables, even private variables, and
I demonstrated this in my code to my satisfaction. Would you like to
see a copy? Just open any textbook on C# and look under "Get" and
"Set" for Properties.

You remind me of the college professor who lost his keys in the dark,
and kept vainly looking under a street lamp far away from where he
lost them. When asked if he found the keys, he replied, "well, I
didn't lose my keys here, but this is the only place I know that has
light!" LOL, that's you Jon. You're answering a question that I didn't
pose (or perhaps I did pose, 'in your mind's eye'?).
>
The point being: *you need a forward reference if the Class1 is not
'nested' in the Form1 {}, that is, if Class1 is part of a separate
translation unit or module, even if Class1 is in the same namespace as
Form1.

No. There is no such thing as a forward reference in C#, and what you
seem to think is a forward reference is actually just a variable
declaration.
OK, let's call the forward declaration a 'variable declaration'. A
rose by any other name...

You're a funny dude. And you're wrong (but not 'in your mind's eye').

RL
Jul 22 '08 #3
raylopez99 <ra********@yah oo.comwrote:
And accessing another type's variables has nothing to do with my
problem, whether you acknowledge it or not.
It has everything to do with the problem you originally described,
which had one form inheriting from another. However, when you came to
show actually code your forms were both inheriting from Form.
BTW, all my variables
were set public and still the code did not work until I hit upon the
parameterised constructor.
Indeed, because your code wasn't how you originally described it. You
claimed an inheritance relationship which simply wasn't there.
Just passing a parameter doesn't mean that Form2 is magically able to
see Form1.myClass1. Form2's constructor will be able to see the
parameter, which starts off with the same value as Form1.myClass1, but
you can't actually refer to the Form1.myClass1 variable from Form2.
You can too. Using the public properties Get and Set, you certainly
can refer to the Form1.myClass1 variables, even private variables, and
I demonstrated this in my code to my satisfaction. Would you like to
see a copy? Just open any textbook on C# and look under "Get" and
"Set" for Properties.
That's not referring to the variables. That's referring to the
properties, which happen to the return the current variable value. Big
difference. Try passing the property by reference, for example...
You remind me of the college professor who lost his keys in the dark,
and kept vainly looking under a street lamp far away from where he
lost them. When asked if he found the keys, he replied, "well, I
didn't lose my keys here, but this is the only place I know that has
light!" LOL, that's you Jon. You're answering a question that I didn't
pose (or perhaps I did pose, 'in your mind's eye'?).
No, I'm answering the question you *did* pose, even though it may not
have reflected reality. You repeatedly stated that the child form
inherited from the parent form - but then your code showed otherwise.
That's what confused me - I foolishly trusted that you were accurately
describing your code.

So yes, I'll take part of the blame for not solving your problem
earlier - but you should also accept your portion of it for
misdescribing it in the first place.
The point being: *you need a forward reference if the Class1 is not
'nested' in the Form1 {}, that is, if Class1 is part of a separate
translation unit or module, even if Class1 is in the same namespace as
Form1.
No. There is no such thing as a forward reference in C#, and what you
seem to think is a forward reference is actually just a variable
declaration.
OK, let's call the forward declaration a 'variable declaration'. A
rose by any other name...
Um, no. A forward declaration in C++ is not the same thing as a
variable declaration at all.
You're a funny dude. And you're wrong (but not 'in your mind's eye').
Fine, you believe that. Just don't expect people to keep trying to help
you when you refuse to use correct terminology, misdescribe your
situation, and then claim to know better than they do despite making
wild claims about how the language works. I enjoy teaching and
coaching, which is why I participate here - but it's got to be a two-
way process.

--
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 #4
On Jul 22, 5:12*am, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
raylopez99 <raylope...@yah oo.comwrote:
And accessing another type's variables has nothing to do with my
problem, whether you acknowledge it or not.

It has everything to do with the problem you originally described,
which had one form inheriting from another. However, when you came to
show actually code your forms were both inheriting from Form.
BTW, all my variables
were set public and still the code did not work until I hit upon the
parameterised constructor.

Indeed, because your code wasn't how you originally described it. You
claimed an inheritance relationship which simply wasn't there.
Yes, it's true, I did have three different problems, because before
hitting upon the solution, which was the parametrical constructor, I
tried various things like setting Form2:Form1.

BTW, I don't think setting Form2 to inherit from Form1 will solve the
problem without the use of a parametrical constructor, as I thought I
tried this, but maybe it will--time to do a quick test of this thesis
before I post...time out while I check this...making sure all
variables are public in both the base class and derived class... OK,
after many permutations, I confirm you cannot "see" any derived class
in Form 2 that's been instantiated in Form1, either, whether or not
Form2: Form1 or Form2: Form, unless you pass the derived class in the
parametized constructor, just like I said in this thread.
>
Just passing a parameter doesn't mean that Form2 is magically able to
see Form1.myClass1. Form2's constructor will be able to see the
parameter, which starts off with the same value as Form1.myClass1, but
you can't actually refer to the Form1.myClass1 variable from Form2.
I think we're talking two different things. If, referring to this
passage:

(#1) And just to make the point clearer, Form2 must have as a
constructor something besides the normal (default) non parameter
constructor, along these lines:

public Form2(Class1 passClass1_from _Form1)
{
myClass2_that_e xists_in_Form2 = passClass1_from _Form1; //
names are arbitrary of course
InitializeCompo nent();
// other stuff here if you want
}

I'm not entirely sure you're correct [UPDATE: after running the tests
below, I'm sure that a person--not you--but a person who says an
object that is passed to Form2 using the parametric constructor of
Form2 from Form1 is not passing the true object but a copy of the
object is not correct] if you say myClass2_that_e xists_in_Form2 cannot
"actually refer to the Form1.myClass1 'variable' from Form2, since we
are passing by value, so it must refer to it. But I think you're
trying to say [THIS IS WHAT I TESTED BELOW--IT MAY NOT BE WHAT YOU
WERE SAYING, BUT IT WAS INTERESTING FOR ME--RL] it cannot permanently
change the variables (let's assume they are all public) in
Form1.myClass1 since we are not using the 'ref' keywords to pass by
reference. But, as we know, if you add the "ref" keyword, and with a
helper function we can change a class (we can put the helper function
in another class, or as a standalone function, that accepts 'ref
Class2'), however, the issue here is (and this may or may not be what
you have in mind) whether to use the above example
"myClass2_that_ exists_in_Form2 " can permanently change any public
variable in class "passClass2[1]_from_Form1", via changes made in
Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]

There's only one way to find out, and that's to test this
hypothesis...ti meout while I test this...I will pass a 'myClass2' from
Form1 to Form2, using the parametric constructor, then change a public
variable of myClass2 in Form2, then see if it's changed when I go back
to Form1...the hypothesis being tested is that it's probably true that
no change will be made to the Form1 'myclass' [UPDATE: AND THIS
'HYPOTHESIS' IS WRONG-RL]--but let's see...

Ah, OK, about 60 minutes later...found out you're WRONG AGAIN JONNY!!!
AHAHAHAHA. Hey just kidding, we're talking (I hope) about two
different things.

Here's what I did, which probably will meet with an objection or two,
but here goes: in Form1 I instantiated two classes, class 2 [call it
"OriginalClass2 "], and class 3, see below at **1**. Class 3 is a
'helper' class that changes public variables in class 2 by two
methods, one method that takes a 'ref' keyword (pass by ref) {public
void refMethodChange Class2 (ref Class2 x)} and the other method,
{noRefMETHODCl2 (Class2 y)}, that changes public variables in class 2
by taking class 2 via pass-by-value, each method accepting a Class2
object.

Now, in Form2, I instantiate two classes Class2, call it
myForm1Class2, and Class3, call it myForm1Class3, and accept the Form1
class 2 and 3 as follows:

**2**
public Form2(Class1 passClass1, Class2 passClass2, Class3
passClass3) //parametic normal constructor: accepts two classes
{
myForm1Class2 = passClass2;
myForm1Class3 = passClass3;
InitializeCompo nent();

}

Now, again in Form2, I change two public member variables in Class 2
(myForm1Class2) via the 'helper' class 3 methods discussed above,
refMethod and noRefMETH..., which 'live' in myForm1Class3. [Update:
BTW, as described below, no need for a 'new' to be used for
myForm1Class2 and myForm1Class3]

It's not important as to what I change IMO, but FYI I changed this:

public void refMethodChange Class2 (ref Class2 x)
{
x.interger02 = 999887; //picking an arbitrary big number
just to stand out //ref change method, note keyword 'ref'
x.arr2[0] = 555;
}

public void noRefMETHODCl2( Class2 y)
{
y.interger02 = 661100; //no ref change method
y.arr2[0] = 444;
}

The point being, this is done in Form2 on instances of class Class2
passed to Form2 via the parametic constructor. If 'your' theory, (not
really your, it's just a rhetorical phrase), is correct, then when I
check public members Class2.interger 02 and Class2.ar2[0], in *form
Form1*, after making these changes using the 'helper' class functions
refMethod.. and noRefMETHOD... *in form Form2*, I 'might' think that I
would not change the original class 2, namely, "myForm1Class2" ? Yes?
No? BUT NO! That's right, using EITHER of the two 'helper'
functions, the public members .interger02 and .arr2 are permanently
changed for "myForm1Cla ss2" in "OriginalClass2 " (which lives in Form1)
and these changes were done in Form2, not Form 1!

Put that in your hookah and smoke it!!! Smoking!! Flame on!

What this shows is: indeed, when you pass an object using the
parametrized normal constructor, and, surprisingly, even if you don't
use 'new' in the child Form2 parametricized [sic] contructor (see
***3** below for a counter example that worked the same), you are
passing the actual object and not a copy of the object, and any
changes made, either with pass by value or pass by method, will change
the object, subject to the 'usual rules' about pass by ref and pass by
value. What are these 'usual rules'? You know better than I, but
literally it's the web page you designed for newbies, which I refer to
all the time, describing when you should pass by value and when pass
by ref, which I have in my library and refer to from time to time.
But those 'usual rules' are not applicable here, in the sense that
they don't come into play.

On this last point, when I said "surprising ly" above, it's because
'new' doesn't play any role. For example, in form Form2 the following
parametric constructor worked the same as the one in ***2**, which did
not use 'new', which proves (in my mind's eye) that no 'copies' are
being passed, because, as you Jon show (or seem to show) in your web
page on pass-by-ref versus pass-by-value, if local copies were being
made, then 'new' would certainly make a difference.

***3**
public Form2(Class1 passClass1, Class2 passClass2, Class3 passClass3)
{
//myClass2 = passClass2;
//myNewClass1 = passClass1;
//Works3DerivedCl ass = passClass3; //the below lines work
EXACTLY like these three previous lines--so 'new' is irrelevant!

myClass2 = new Class2();
myClass2 = passClass2;
myNewClass1 = new Class1();
myNewClass1 = passClass1;
Works3DerivedCl ass = new Class3();
Works3DerivedCl ass = passClass3;
InitializeCompo nent();
}
// end of example ***3***

//Start of example **1**

**1**
public class Class2
{

public string str02;
public int interger02;
public int[] arr2;

public Class2()
{
str02 = "hi2";
interger02 = 1;
arr2 = new int[] {0,1,2};
}
public Class2(int i, string s)
{
str02 = s;
interger02 = i;
arr2 = new int[] { 0, 1, 2 };
}

}

public class Class3
{
public int Int3;
public Class3()
{
Int3 = 111;
}

public void refMethodChange Class2 (ref Class2 x)
{
x.interger02 = 999887; //ref
x.arr2[0] = 555;
}

public void noRefMETHODCl2( Class2 y)
{
y.interger02 = 661100; //no ref
y.arr2[0] = 444;
}

}

// end of example **1**
You can too. *Using the public properties Get and Set, you certainly
can refer to the Form1.myClass1 variables, even private variables, and
I demonstrated this in my code to my satisfaction. *Would you like to
see a copy? *Just open any textbook on C# and look under "Get" and
"Set" for Properties.

That's not referring to the variables. That's referring to the
properties, which happen to the return the current variable value. Big
difference. Try passing the property by reference, for example...
OK, fine, I agree. Different issue, yes, you're right here, and so
was I, but we're talking different stuff, like you acknowledge.

You remind me of the college professor who lost his keys in the dark,
and kept vainly looking under a street lamp far away from where he
lost them. *When asked if he found the keys, he replied, "well, I
didn't lose my keys here, but this is the only place I know that has
light!" LOL, that's you Jon. You're answering a question that I didn't
pose (or perhaps I did pose, 'in your mind's eye'?).

No, I'm answering the question you *did* pose, even though it may not
have reflected reality. You repeatedly stated that the child form
inherited from the parent form - but then your code showed otherwise.
That's what confused me - I foolishly trusted that you were accurately
describing your code.

So yes, I'll take part of the blame for not solving your problem
earlier - but you should also accept your portion of it for
misdescribing it in the first place.
I was teasing you, a flame, nothing more. Both of us are "right",
but, like the pig in Charlotte's Web, or was that Animal Farm, I'm
more right...haha. Kidding. I take blame for switching the goal
posts a bit, true.

>
The point being: *you need a forward reference if the Class1 is not
'nested' in the Form1 {}, that is, if Class1 is part of a separate
translation unit or module, even if Class1 is in the same namespaceas
Form1.
No. There is no such thing as a forward reference in C#, and what you
seem to think is a forward reference is actually just a variable
declaration.
OK, let's call the forward declaration a 'variable declaration'. *A
rose by any other name...

Um, no. A forward declaration in C++ is not the same thing as a
variable declaration at all.
OK, you win on this point. My bad. I'll call it a 'variable
declaration' even though a class object is being declared, not a
primitive data like int, double, etc, which I like to think as
'variables' in my mind's eye.
I enjoy teaching and
coaching, which is why I participate here - but it's got to be a two-
way process.
I appreciate your help, even though I like to flame as you can tell.
Comes from being anonymous (which I'm not entirely, since a few people
in the real world know who I am under this name, my old boss for
example, but for the most part I'm anonymous). Of course I learn a
lot just trying to prove stuff, even just now I wasted an hour of my
life but learned something new, as per the above.

Thanks for your help Jon! I read your stuff all the time and pick up
pointers here and there.

RL
Jul 22 '08 #5
raylopez99 <ra********@yah oo.comwrote:
Indeed, because your code wasn't how you originally described it. You
claimed an inheritance relationship which simply wasn't there.

Yes, it's true, I did have three different problems, because before
hitting upon the solution, which was the parametrical constructor, I
tried various things like setting Form2:Form1.

BTW, I don't think setting Form2 to inherit from Form1 will solve the
problem without the use of a parametrical constructor, as I thought I
tried this, but maybe it will--time to do a quick test of this thesis
before I post...time out while I check this...making sure all
variables are public in both the base class and derived class... OK,
after many permutations, I confirm you cannot "see" any derived class
in Form 2 that's been instantiated in Form1, either, whether or not
Form2: Form1 or Form2: Form, unless you pass the derived class in the
parametized constructor, just like I said in this thread.
If Form2 : Form1, then from Form2 you will be able to see any variables
in Form1 which are declared as public or protected (or internal if
they're in the same assembly).
Just passing a parameter doesn't mean that Form2 is magically able to
see Form1.myClass1. Form2's constructor will be able to see the
parameter, which starts off with the same value as Form1.myClass1, but
you can't actually refer to the Form1.myClass1 variable from Form2.

I think we're talking two different things. If, referring to this
passage:

(#1) And just to make the point clearer, Form2 must have as a
constructor something besides the normal (default) non parameter
constructor, along these lines:

public Form2(Class1 passClass1_from _Form1)
{
myClass2_that_e xists_in_Form2 = passClass1_from _Form1; //
names are arbitrary of course
InitializeCompo nent();
// other stuff here if you want
}
Alternatively, Form2 could have a parameterless constructor and you
could set properties, or call methods to pass it the information.
Constructors aren't the only way to pass information between objects.
I'm not entirely sure you're correct [UPDATE: after running the tests
below, I'm sure that a person--not you--but a person who says an
object that is passed to Form2 using the parametric constructor of
Form2 from Form1 is not passing the true object but a copy of the
object is not correct]
You're neither passing "the true object" nor a copy of the object.
You're passing a reference to the object.
if you say myClass2_that_e xists_in_Form2 cannot
"actually refer to the Form1.myClass1 'variable' from Form2, since we
are passing by value, so it must refer to it.
No, not at all. You have passed the current value of the variable as
the argument. If you change the value of Form1.myClass1, there will be
no way for Form2 to retrieve it. It doesn't have access to the
*variable*.
But I think you're
trying to say [THIS IS WHAT I TESTED BELOW--IT MAY NOT BE WHAT YOU
WERE SAYING, BUT IT WAS INTERESTING FOR ME--RL] it cannot permanently
change the variables (let's assume they are all public) in
Form1.myClass1 since we are not using the 'ref' keywords to pass by
reference.
Passing by reference would effectively give temporary (i.e. duration of
the constructor) access to the variable, yes. However, you can't take
an arbitrary reference to an instance of Form1 and access its myClass1
variable from Form2, while the variable is private.
But, as we know, if you add the "ref" keyword, and with a
helper function we can change a class (we can put the helper function
in another class, or as a standalone function, that accepts 'ref
Class2'), however, the issue here is (and this may or may not be what
you have in mind) whether to use the above example
"myClass2_that_ exists_in_Form2 " can permanently change any public
variable in class "passClass2[1]_from_Form1", via changes made in
Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]
Reference parameters do effectively change the situation somewhat, but
it's important to note that Form2 doesn't really know that it's
Form1.myClass1 that's been passed to it by reference. It could be a
local variable, or a variable from something completely different.
There's only one way to find out, and that's to test this
hypothesis...ti meout while I test this...I will pass a 'myClass2' from
Form1 to Form2, using the parametric constructor, then change a public
variable of myClass2 in Form2, then see if it's changed when I go back
to Form1...the hypothesis being tested is that it's probably true that
no change will be made to the Form1 'myclass' [UPDATE: AND THIS
'HYPOTHESIS' IS WRONG-RL]--but let's see...

Ah, OK, about 60 minutes later...found out you're WRONG AGAIN JONNY!!!
AHAHAHAHA. Hey just kidding, we're talking (I hope) about two
different things.

Here's what I did, which probably will meet with an objection or two,
but here goes: in Form1 I instantiated two classes, class 2 [call it
"OriginalClass2 "], and class 3, see below at **1**. Class 3 is a
'helper' class that changes public variables in class 2 by two
methods, one method that takes a 'ref' keyword (pass by ref) {public
void refMethodChange Class2 (ref Class2 x)} and the other method,
{noRefMETHODCl2 (Class2 y)}, that changes public variables in class 2
by taking class 2 via pass-by-value, each method accepting a Class2
object.
<snip>

Rather than me explaining reference parameters here, I suggest you read
my article on them:
http://pobox.com/~skeet/csharp/parameters.html

You still seem confused about the difference between passing a
reference by value and passing a parameter *by* reference. Changing the
*contents* of an object doesn't change the value of a variable which
refers to that object.

Hopefully the article above will clarify things for you.

<snip>
Um, no. A forward declaration in C++ is not the same thing as a
variable declaration at all.

OK, you win on this point. My bad. I'll call it a 'variable
declaration' even though a class object is being declared, not a
primitive data like int, double, etc, which I like to think as
'variables' in my mind's eye.
You should adjust your meaning of the word variable then. And no, a
class *object* isn't being declared - a *variable* is being declared.
Just because there's a variable doesn't mean any object is necessarily
being created. The variable may have a null value, or refer to an
object which was created elsewhere. For instance:

StringBuilder sb1 = new StringBuilder() ;
StringBuilder sb2 = sb1;

That has declared two variables, but only one object has been created.

--
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 #6
On Jul 22, 11:54 am, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
Alternatively, Form2 could have a parameterless constructor and you
could set properties, or call methods to pass it the information.
Constructors aren't the only way to pass information between objects.
What are the other ways? Passing a class that has a method X that
accepts other classes is of course one way, but for all practical
purposes it's the same as the parameterized copy constructor, with the
important difference of course that you can call this method X many
times, not just once. Another way is the inheritance of forms, Form2:
Form1 as you discuss below and as I further comment below. Another
way maybe is the publisher-subscriber events/delegates model? But I'm
not sure, since Forms, unlike Console mode, has some tricks to it
(discussed below).

I'm not entirely sure you're correct [UPDATE: after running the tests
below, I'm sure that a person--not you--but a person who says an
object that is passed to Form2 using the parametric constructor of
Form2 from Form1 is not passing the true object but a copy of the
object is not correct]

You're neither passing "the true object" nor a copy of the object.
You're passing a reference to the object.
Yes, because we're dealing with a managed language C#. Is that your
point? OK. A small point but noted.
>
if you say myClass2_that_e xists_in_Form2 cannot
"actually refer to the Form1.myClass1 'variable' from Form2, since we
are passing by value, so it must refer to it.

No, not at all. You have passed the current value of the variable as
the argument. If you change the value of Form1.myClass1, there will be
no way for Form2 to retrieve it. It doesn't have access to the
*variable*.
Not true. You might have something else in mind. I am finding out
that both in what I call the non-inherited model of Form1: Form and
Form2: Form, where I use a parameterized constructor to pass the
class2 that has the information in it, and the inhereited model of
Form2: Form1, that you suggested, I am getting "data binding" between
the two forms in both directions. That is, with one small, trivial
bug exception that I discuss below with inherited controls, I am
getting both the public variable arr2 of Class2 to 'update' in both
the Form1 (parent) and Form2 (child) when I make a change to arr2 in
either parent or child forms (Forms 1 or Form 2, respectively). That
is data binding in both directions. It's working. The small
exception? When I inherit forms, Form 2 gets all the controls from
Form1 (which BTW is very confusing and I would never do this in
practice, but it's just a demo), and because of some obscure way form
controls are instantiated, or perhaps something else, when I try and
update arr2 using the inherited child form control button (but not the
parent form control button), I get an 'old' value. But this is a
minor bug or rather just an inherited control problem, or some small
thing. The main thing is that using my system or your system I am
getting data binding in both directions.
>
But I think you're
trying to say [THIS IS WHAT I TESTED BELOW--IT MAY NOT BE WHAT YOU
WERE SAYING, BUT IT WAS INTERESTING FOR ME--RL] it cannot permanently
change the variables (let's assume they are all public) in
Form1.myClass1 since we are not using the 'ref' keywords to pass by
reference.

Passing by reference would effectively give temporary (i.e. duration of
the constructor) access to the variable, yes.
But, even using non-pass-by-reference or pass-by-value, I'm getting
data binding in both directions, between parent and child (forms 1 and
2), like I said above. Even with pass-by-value when you change the
arr2[0] element of array arr2 in the child, the parent form shows it
also being changed, and when you change it in the parent the child
form class (which as a different name, but, we agree, it's the same
reference to the same object) also changes. In short, data binding in
both directions; it's working, insofar as I can tell.
However, you can't take
an arbitrary reference to an instance of Form1 and access its myClass1
variable from Form2, while the variable is private.
Yes. You keep saying this, and this is a newbie point well taken, but
we (I) am beyond that. One funny thing I keep forgetting is that C#
likes to always express access modifiers everywhere, with no access
modifier being private by default. But for this example I set
everything to public, using keyword 'public'. Everything, so this
point is moot? (but see the note at the end here about 'class0')
>
But, as we know, if you add the "ref" keyword, and with a
helper function we can change a class (we can put the helper function
in another class, or as a standalone function, that accepts 'ref
Class2'), however, the issue here is (and this may or may not be what
you have in mind) whether to use the above example
"myClass2_that_ exists_in_Form2 " can permanently change any public
variable in class "passClass2[1]_from_Form1", via changes made in
Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]

Reference parameters do effectively change the situation somewhat, but
it's important to note that Form2 doesn't really know that it's
Form1.myClass1 that's been passed to it by reference. It could be a
local variable, or a variable from something completely different.
It could be, but for some reason, like I said, when you change the
parameter in Form 2, form Form1 is also updated, even when the forms
are not inherited. If you feel this fact is shocking, unjustified,
unexplained or whatever, let me know and I'll post the code. I think
it's routine myself--just conventional data binding when you pass one
class (or variable) to another. I'll tell you what I feel is
shocking, below (keep reading--keyword 'class0' and 'nested classes').
>
<snip>

Rather than me explaining reference parameters here, I suggest you read
my article on them:http://pobox.com/~skeet/csharp/parameters.html
This is the article that I mentioned that I already have btw. It
doesn't explain much for this forms example.
>
You still seem confused about the difference between passing a
reference by value and passing a parameter *by* reference. Changing the
*contents* of an object doesn't change the value of a variable which
refers to that object.
Agreed. So? I don't seem confused over that.
>
You should adjust your meaning of the word variable then. And no, a
class *object* isn't being declared - a *variable* is being declared.
Just because there's a variable doesn't mean any object is necessarily
being created. The variable may have a null value, or refer to an
object which was created elsewhere. For instance:

StringBuilder sb1 = new StringBuilder() ;
StringBuilder sb2 = sb1;

That has declared two variables, but only one object has been created.
Good point. I'll use variable then.

OK, here is what I found "shocking". I took your suggestion and for
one version of this program I used inheritance, like I said above, as
in Form1: Form and Form2: Form1 <--note the inheritance (the other
version, which also works, uses two 'independent' forms Form1: Form
and Form2: Form). Both the inherited and non-inherited versions use
the parametricized constructor to pass classes 1 and 2, but,
crucially, I added a third class, class 0, that was nested. This
class 0 was nested and declared public (twice) within Form1, and thus
could be 'seen' (by Intellisense, and ultimately by the program)
unlike declared Classes 1 and 2 (using "Add" to the Solution), which
had their own modules/translation units, unnested, outside of Form1.

Specifically, consider 'nested' class 0 as follows, which is properly
seen by base Form 1 and derived Form2. Comments //!! below

namespace MDIForms
{

public partial class Form1 : Form
{
Class1 myClass1; //though these are public, do they now become
'private' since no keyword public? That is the question!
Class2 aNew2Class; // " "

public Class0 myClass0; // !! keyword 'public' required!!
Shocking, no?!!

//note!!! 'FORWARD DECLARATION STEP' - required that keyword 'public'
be used here: public Class0 myClass0;/!! note this!!! nested class
'myClass0' will not be seen in Form2:Form1 if you don't use access
modifier keyword public here, even though public declared for this
class Class0 below! Further, you CANNOT comment out this line
(program won't compile)

public class Class0 //DEFINITION/CONSTRUCTION STEP - a nested
class within the public partial class Form1 : Form
{
public string str01;
public int interger01;
public Class0()
{
str01 = "hi";
interger01 = 1;

}
public Class0(int i, string s)
{
str01 = s;
interger01 = i;
}

}
public Form1()
{

InitializeCompo nent();

myClass0 = new Class0(47,"heyC lass0base"); //!!
instantiation of the public nested class myClass0

}

private void clikMeNewFToolS tripMenuItem_Cl ick(object sender,
EventArgs e)
{

Form2 frm2 = new Form2(myClass1, aNew2Class); //!! note:
parameterized constructor does NOT send myClass0, but since public and
since nested within Form1, which is inherited by Form2, it is 'seen'
in Form2

frm2.Show();
}

// NOW TURNING TO Form2:

public Form2(Class1 passClass1, Class2 passClass2)
{
myClass2 = passClass2;
myNewClass1 = passClass1;

InitializeCompo nent();

}

private void button1_Click(o bject sender, EventArgs e)
{
string temp = myClass0.str01; //!! note--class0 *is* seen
by Form2, because it's a nested public class in base class Form1

MessageBox.Show ("Class 0 from form2!: " + temp); //shows
"Class 0 from form2!: heyClass0base"
}

//////////////// END

The point: class 0 instantiated in the base class Form1 can only be
seen in derived class Form 2 iff three conditions are met:

(1) it must be nested within Form1

(2) it must be declared as public during the DEFINITION/CONSTRUCTION
STEP above

(3) importantly, it must in the declaration (what I call the FORWARD
DECLARATION STEP above) before the class is defined/constructed, be
declared as "public".

Perhaps, and I could use your input, the problem 'earlier' in this
thread is that classes 1 and 2, which are not nested, are not
explictly declared prior to the Form1 contructor with the keyword
'public', and, though in their respective modules I declare them as
'public', this makes them 'private' somehow when declared within Form
1 without the keyword 'public' (that is truly shocking if true).

Thanks for your help so far. I look forward to your reply.

RL
Jul 22 '08 #7
raylopez99 <ra********@yah oo.comwrote:
Alternatively, Form2 could have a parameterless constructor and you
could set properties, or call methods to pass it the information.
Constructors aren't the only way to pass information between objects.

What are the other ways?
I just listed two: call a method, set a property. You mentioned some
others yourself. My point is that your claim on the first message of
this thread:

<quote>
If you want to pass information between two forms comprised of
classes, whether or not they are parent/child, modal or modeless,
dialog or non-dialog you have to use the non-normal/ non-default or
parametricized or parameter constructor, not a default (no parameter)
normal constructor.
</quote>

is incorrect. A constructor is *one* way of passing information, but
not the only way.
Passing a class that has a method X that
accepts other classes is of course one way, but for all practical
purposes it's the same as the parameterized copy constructor
Be careful here - you haven't created any copy constructors. Giving
constructors parameters isn't the same as creating a copy constructor.
with the important difference of course that you can call this method
X many times, not just once. Another way is the inheritance of forms,
Form2: Form1 as you discuss below and as I further comment below.
Another way maybe is the publisher-subscriber events/delegates model?
But I'm not sure, since Forms, unlike Console mode, has some tricks
to it (discussed below).
There's not really a "Console mode" beyond whether or not a console is
allocated at startup. You can display GUIs in console applications.

Furthermore, the language itself really doesn't care about all of this
- parameter passing, constructors etc remain consistent whatever you're
doing (with some oddities around remoting and the like, admittedly).
I'm not entirely sure you're correct [UPDATE: after running the tests
below, I'm sure that a person--not you--but a person who says an
object that is passed to Form2 using the parametric constructor of
Form2 from Form1 is not passing the true object but a copy of the
object is not correct]
You're neither passing "the true object" nor a copy of the object.
You're passing a reference to the object.

Yes, because we're dealing with a managed language C#. Is that your
point? OK. A small point but noted.
No, it's not a small point at all. It lies at the heart of what you're
seeing when it comes to what you're calling data binding.
if you say myClass2_that_e xists_in_Form2 cannot
"actually refer to the Form1.myClass1 'variable' from Form2, since we
are passing by value, so it must refer to it.
No, not at all. You have passed the current value of the variable as
the argument. If you change the value of Form1.myClass1, there will be
no way for Form2 to retrieve it. It doesn't have access to the
*variable*.

Not true. You might have something else in mind. I am finding out
that both in what I call the non-inherited model of Form1: Form and
Form2: Form, where I use a parameterized constructor to pass the
class2 that has the information in it, and the inhereited model of
Form2: Form1, that you suggested, I am getting "data binding" between
the two forms in both directions.
No, you're not. You can't make any changes to the *variable* of one of
the forms. Sure, you can make changes to the object that the variable
originally refers to, but you can't make the variable refer to a
different object completely (unless you use a ref parameter to start
with, of course - and then only during that call).
That is, with one small, trivial
bug exception that I discuss below with inherited controls, I am
getting both the public variable arr2 of Class2 to 'update' in both
the Form1 (parent) and Form2 (child) when I make a change to arr2 in
either parent or child forms (Forms 1 or Form 2, respectively).
Well, you haven't shown any code with a variable called arr2 in.
However, I strongly *strongly* suspect that you're not changing the
value of the variable - you're changing the contents of the array.

Unless you have

arr2 = [some value];

you're not changing the value of arr2. Certainly this:

arr2[0] = [some value];

isn't doing it. The value of arr2 is just a reference - and that
reference doesn't get changed just because you're changing the contents
of the array, any more than your home address changes if you decorate a
bedroom.

It's very important to understand the difference between a variable,
its value, and the object it happens to refer to at a particular point
in time.
That
is data binding in both directions. It's working. The small
exception? When I inherit forms, Form 2 gets all the controls from
Form1 (which BTW is very confusing and I would never do this in
practice, but it's just a demo), and because of some obscure way form
controls are instantiated, or perhaps something else, when I try and
update arr2 using the inherited child form control button (but not the
parent form control button), I get an 'old' value. But this is a
minor bug or rather just an inherited control problem, or some small
thing. The main thing is that using my system or your system I am
getting data binding in both directions.
Another use of incorrect terminology: data binding isn't what you think
it is.
However, you can't take
an arbitrary reference to an instance of Form1 and access its myClass1
variable from Form2, while the variable is private.

Yes. You keep saying this, and this is a newbie point well taken, but
we (I) am beyond that. One funny thing I keep forgetting is that C#
likes to always express access modifiers everywhere, with no access
modifier being private by default. But for this example I set
everything to public, using keyword 'public'. Everything, so this
point is moot? (but see the note at the end here about 'class0')
When the fields are public then yes, you can change the values of
variables (so long as you have a reference to an instance of the
containing class, of course).
But, as we know, if you add the "ref" keyword, and with a
helper function we can change a class (we can put the helper function
in another class, or as a standalone function, that accepts 'ref
Class2'), however, the issue here is (and this may or may not be what
you have in mind) whether to use the above example
"myClass2_that_ exists_in_Form2 " can permanently change any public
variable in class "passClass2[1]_from_Form1", via changes made in
Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]
Reference parameters do effectively change the situation somewhat, but
it's important to note that Form2 doesn't really know that it's
Form1.myClass1 that's been passed to it by reference. It could be a
local variable, or a variable from something completely different.

It could be, but for some reason, like I said, when you change the
parameter in Form 2, form Form1 is also updated, even when the forms
are not inherited. If you feel this fact is shocking, unjustified,
unexplained or whatever, let me know and I'll post the code. I think
it's routine myself--just conventional data binding when you pass one
class (or variable) to another. I'll tell you what I feel is
shocking, below (keep reading--keyword 'class0' and 'nested classes').
Yes, nested classes have access to private members in their enclosing
class. That's not shocking to me, because it's part of the spec. As for
the rest, it's a simple matter of understanding the difference between
an object and a reference.
Rather than me explaining reference parameters here, I suggest you read
my article on them:http://pobox.com/~skeet/csharp/parameters.html

This is the article that I mentioned that I already have btw. It
doesn't explain much for this forms example.
Your forms example is still massively incomplete.
You still seem confused about the difference between passing a
reference by value and passing a parameter *by* reference. Changing the
*contents* of an object doesn't change the value of a variable which
refers to that object.

Agreed. So? I don't seem confused over that.
Yes, you do. You keep claiming to be able to change the value of a
variable you don't have access to, just because you can change the
contents of the object that the variable happens to refer to. They're
not the same thing.
OK, here is what I found "shocking". I took your suggestion and for
one version of this program I used inheritance, like I said above, as
in Form1: Form and Form2: Form1 <--note the inheritance (the other
version, which also works, uses two 'independent' forms Form1: Form
and Form2: Form). Both the inherited and non-inherited versions use
the parametricized constructor to pass classes 1 and 2, but,
crucially, I added a third class, class 0, that was nested. This
class 0 was nested and declared public (twice) within Form1, and thus
could be 'seen' (by Intellisense, and ultimately by the program)
unlike declared Classes 1 and 2 (using "Add" to the Solution), which
had their own modules/translation units, unnested, outside of Form1.
This is part of the problem - instead of trying to isolate one single
piece of how the language behaves, you're coming up with massive
examples with non-descriptive names (Class1, Class2, Class3, Form1,
Form2) and making them *much* more complicated than they need to be.
Why involve designer classes (which you never post), partial classes,
inheritance *and* nested classes all in the same example? Stick to one
at a time, preferably in a simple Console app which doesn't require any
extra code. Your examples would be *much* clearer that way.

Your code is even incomplete in the non-designer classes - you haven't
shown where Form2 is declared.
Specifically, consider 'nested' class 0 as follows, which is properly
seen by base Form 1 and derived Form2. Comments //!! below

namespace MDIForms
{

public partial class Form1 : Form
{
Class1 myClass1; //though these are public, do they now become
'private' since no keyword public? That is the question!
Class2 aNew2Class; // " "

public Class0 myClass0; // !! keyword 'public' required!!
Shocking, no?!!
Required to do what? To see it from Form2? No, it can be private. It
can also be declared anywhere in the class, even after the nested
class, contrary to your later assertion. Here's an example:

using System;

class Test
{
static void Main()
{
Test t = new Test();
t.privateVariab le = "private";
new Nested().ShowPr ivateVariable(t );
}

class Nested
{
internal void ShowPrivateVari able(Test t)
{
Console.WriteLi ne(t.privateVar iable);
}
}

private string privateVariable ;
}

That example is *complete* - you can cut and paste it into a new text
file, then run csc on it and run the resulting executable. I would
greatly appreciate it if you would follow the same model. At the moment
it's like being asked to guess which number you're thinking of.
//note!!! 'FORWARD DECLARATION STEP'
Why are you still using terminology that you're aware is incorrect?

<snip incomplete code>
Perhaps, and I could use your input, the problem 'earlier' in this
thread is that classes 1 and 2, which are not nested, are not
explictly declared prior to the Form1 contructor with the keyword
'public', and, though in their respective modules I declare them as
'public', this makes them 'private' somehow when declared within Form
1 without the keyword 'public' (that is truly shocking if true).

Thanks for your help so far. I look forward to your reply.
If you would post a short but *complete* program which demonstrates
something strange.

Note that there's a big difference between declaring a *variable* as
public and declaring a *class* as public. In the paragraph above you
seem to be conflating the two ideas.

--
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 #8
raylopez99 <ra********@yah oo.comwrote:

<snip>
OK, see below for an example, but keep in mind your console mode
example fails to be instructive for several reasons: (1) it's console
mode not Forms. Totally different, and if you don't see it that way no
use further discussing this issue.
In that case I guess it's the end of the discussion. Forms apps aren't
nearly as different as you seem to believe, and until you accept that I
suspect this conversation really won't go anywhere. In particular,
these things don't change at all when considering Forms apps:

1) There still has to be an entry point - a Main method
2) The Main method still has to be in a type, because all methods are
within types in C#.
3) Partial classes work the same with forms as with any other classes.
4) There's still no such thing as a forward declaration.
5) Pass-by-reference vs pass-by-value works exactly the same way
in WinForms apps as console apps (and any other C# code)
6) Class and variable declarations in C# work exactly the same way
in WinForms apps as console apps (and any other C# code)
7) Scoping and access rules in C# work exactly the same way
in WinForms apps as console apps (and any other C# code)

Are you seeing a pattern?

Forms apps are certainly more *complicated* than Console apps, because
there's all the designer code involved, and basically a lot more
*stuff*. But the language itself doesn't change.
Forms have certain 'entry points'
and certain quirks that must be obeyed. (2) you use the convention of
static void Main() being 'nested' inside a class, which does not show
how the nested class is seen by another class in a different
translation unit.
Please show who you could possibly have the Main method *not* in a
class or struct.
It goes to the heart of why form Form2:Form1 cannot
'see' Class0 unless Class0 is declared public *twice*, not just nested
with keyword public, but in the declaration public Class0 myClass0;
before the class Class0 is defined.
That's not declaring a class. That's declaring a variable called
myClass0, of *type* Class0. The sooner you understand that, the better.
Unless you use the "class" keyword, you're *not* declaring a class.
Perhaps, and I could use your input, the problem 'earlier' in this
thread is that classes 1 and 2, which are not nested, are not
explictly declared prior to the Form1 contructor with the keyword
'public', and, though in their respective modules I declare them as
'public', this makes them 'private' somehow when declared within Form
1 without the keyword 'public' (that is truly shocking if true).
Thanks for your help so far. *I look forward to your reply.
If you would post a short but *complete* program which demonstrates
something strange.
You did not even attempt to answer my question "Perhaps, and I could
use your input".
No, but I said what you needed to do for me to answer it: post a short
but complete program. When you do that, I'll answer your question.
Shows me you're still unaware of the complexity of
Forms, and the 'entry points' that I alluded to (which I would hazard
you don't even know exist).
Oh you really are priceless. Did you behave the same way with your
teachers at school? Yes, I'm very aware of entry points, thank you.
But, since a teacher learns from his
students almost as much as the students learn from the teacher, I will
give you a short example of this phenomena--and I encourage you to
replicate this problem in "Forms", not console mode.
Oh look, it's another incomplete example. See
http://pobox.com/~skeet/csharp/incomplete.html

(Hint: It's perfectly possible to post a complete WinForms program if
you really want to. You just haven't done so. It would be far simpler
to stick to console apps though.)
If you understand this simple example you're half way towards
understanding the problem in this thread.
I understand everything that occurs in the C# language in this thread.
I don't understand some of what you're trying to communicate because
you persist in talking inaccurate terms (such as "forward references")
and posting incomplete programs.

If you'd post a complete program which either you believe goes against
something I've said, or which contains some aspect you don't
understand, we may be able to make some progress.

--
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 23 '08 #9
On Jul 23, 12:56 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
raylopez99 <raylope...@yah oo.comwrote:
In that case I guess it's the end of the discussion.
I did learn a few things in this exchange, which I'll summarize
below. Thanks for replying.
>
I have explained numerous times that the best way of helping me to help
you with your "newbie concerns" is to post short but complete programs.
This is advice I've given to many, many people on many, many occasions
- and those that have followed it have almost always been glad they've
done so. It just makes life so much easier.
I didn't realize you were such a stickler for complete code, I assumed
you were just being obstinate. I'll make a mental note of it for any
future reference.
>
Forms apps are certainly more *complicated* than Console apps, because
there's all the designer code involved, and basically a lot more
*stuff*. But the language itself doesn't change.
Nobody said the language changed--those are your words.

You claimed forms and console apps were "totally different". They're
not. Even the entry point is the same - a Main method.
OK, if you say so. I don't even know where "Main" is in Windows
anymore, but I assume it's there somewhere.

Including Main in a class isn't the same as creating a nested class -
and it's *always* in a class (or struct) so it's not a "convention " -
it's part of how you *have* to define methods.
Yes, but it doesn't address the issue of scope, etc. But let's move
on.
>
That's not declaring a class. That's declaring a variable called
myClass0, of *type* Class0. The sooner you understand that, the better.
Unless you use the "class" keyword, you're *not* declaring a class.
I need a complete program to make sure that I'm seeing exactly the same
effect as you. It's common to want to be able to reproduce an issue
before commenting on it. It's also common to want to see minimal code
that *does* reproduce an issue. Both of these are most easily achieved
with console apps, when the topics in question aren't inherently
related to GUIs - and the issues you've got here really, *really*
aren't GUI-specific.
But I wrote the program in Windows Form application mode, not console
mode. I could reproduce a Windows Form error in Console mode, I would
be quite the experienced programmer, no? I would know what the error
is, that it's not a Windows specific error, then I would write a
"Console mode" equivalent of the erroneous code, then I would post the
complete console mode code (that's erroneous) for you to comment upon
and find the solution to the error. Needless to say, this is absurd.
If I'm that competent a programmer, I would not need you or anybody
else to spot errors in my code; I would not make errors in the first
place.
>
And you wrote a book? What was it, self published?

I'm not going to start bragging about my book here. Suffice to say the
reviews are pretty positive so far. Look for yourself on amazon.com.
You might even want to read the free chapters which are available fromhttp://manning.com/skeet
This is a good book, an intermediate level book. Just took a look at
Chap. 6, about Iterators, and writing your own, which I just reviewed
a week or so ago online, with multiple 'yield return' statements and
the like. I probably will buy this book, it looks well done. I hate
beginner "Dummies" books, which are good but not enough depth at
times--you need a little meat, like those Scott Meyers books on
Effective C# from the late 1990s.
>
I understand everything that occurs in the C# language in this thread.
I don't understand some of what you're trying to communicate because
you persist in talking inaccurate terms (such as "forward references")
and posting incomplete programs.
OK, OK, I'm just a newbie. And I code for 'fun' --I have a real job.
>
While you fail to use correct terminology, even after being corrected
on it, communication is difficult. Likewise it is harder to comment on
a program when I'm only given half the code.
But your lingo is not conducive to the free flow of information. It's
like first having to repeat a magic number before I get an answer.
You told me the magic number five posts ago, but I forgot it.

I've recognised that you have an issue in terms of your understanding
of scope, access and what you're actually declaring.
Then say so. Do we need to get to this level of back and forth before
you comment? Finally, however, I see you do comment below. A belated
"thanks" I guess.
>
Study and commit to memory, I've added a few Easter Egg comments
tailored just for you Jon:
Here it is:
////////// START OF PARTIAL CLASS FORM1: Form
public partial class Form1 : Form
{
Class1 myClass1; //cannot comment out this line--compile error
<--do you know why, Jon?

Obviously - you're referring to it in the constructor.
Really? A constructor in my "book" is the stuff that appears in public
Form1 () {//here}, but I guess I'm using the wrong lingo again.
Anyway, moving right along...
However, you could move the declaration to after the contructor and
methods - or even to a different file which also declares Form1 (again
as a public partial classs).
Oh, really? OK, I just tried this and it doesn't compile (sorry in
advance about the incomplete code, but you know how that goes)...

///////start
namespace MDIForms
{
Class1 myClass1; //// error CS0116: A namespace does not
directly contain members such as fields or methods

public partial class Form1 : Form
{
//Class1 myClass1; //manditory for compiling

//////end

As you can see, the program did not compile. But I guess once again I
misunderstood, my apologies in advance. Moving right along...
>
Class2 mYClass2;
public Form1()
{
InitializeCompo nent();
// Class1 myClass1 = new Class1(100,
"heLlO1YouTube! "); //
HIDES or 'overrides' previous declaration! <--Jon, does this ring a
bell? Have you done this? If not, why not? Coding style perhaps?

It hides it, yes. I do it occasionally for parameters to constructors,
e.g.

public void Foo (int something)
{
this.something = something;

}

I try to avoid doing it in other cases, however.'
OK, I did get that, I think, as I understand the code fragment you
gave is perfectly legal (this.something =something; is not the same as
something=somet hing;) and gives the intended result, unlike my
commented out code.
>
//if you pass class as above rather than below line, you
get null pointer! -wrong!! <--Jon, do you understand why this is *not*
a null pointer, but a null reference, and why most people think that's
bad, regardless of what you call it?

The default value of a reference type non-local variable is null. As
for whether it's "bad" that depends on the context. Sometimes it's
exactly what you want - but not in this case.
Understood. I even saw in a Windows App event handler some code like:

MyDialogForm01 dlgForm = new MyDialogForm01( );
//stuff deleted here
dlgForm = null; // at end of code; not strictly needed, apparently
some form of manual garbage collection

>
"But give me complete code!" says Jon,
unaware that in Forms some of the complete code can run a few thousand
lines for even a simple windows application!

On the other hand a simple and complete WinForms application is also
feasible in only a few lines of code. For example:

using System;
using System.Drawing;
using System.Windows. Forms;

class Test
{
[STAThread]
static void Main()
{
Form form = new Form {
Controls = { new Button {Name="Button", Text="Click me"}},
Size = new Size(500, 500)
};
form.Controls["Button"].Click += delegate
{ MessageBox.Show ("Hello"); };
Application.Run (form);
}
OK, when I get to that level of sophistication, maybe I won't need you
then.
}
{
Form2 frm2 = new Form2(myClass1, mYClass2); //<--do you
know, reading this thread, why we are using parametric constructors
rather than default parameterless constructors?

Yes, you're using it to pass information to Form2. As we've already
discussed, there are other ways of doing that.
True enough, though in my mind other than the example of inheriting a
form, and using a method from a class that's nested in the base class,
I really don't see how. Far more flexible to pass objects--oops, I
meant variables--to the second or derived form. I mentioned in
passing that you can maybe use delegates/events between forms, but the
more I think about it, the more I see that getting the events
recognized might be a problem. Maybe you can insert "delegate <type>
VariableName (type)" throughout both forms, and maybe that will work,
but without seeing an example I'm not about to waste an hour or two
trying to find out. Besides there's a hoary tradition in C++ of using
the constructor to pass all kinds of information--I'm sure you've seen
the 'modern' constructor format of C++ (which C# sadly does not have)
where you can, after the colon, do stuff like INTergerI(jay),
BooL(true)... etc, which is equal to INergerI = jay; BooL = true;
inside the bracket { } . If you're not familiar with C++ forget all
of this. In short, I like using the constructor to pass objects and
until I see a concrete example (other than the derived classes/ nested
classes example discussed) I'm sticking to that convention, since it
works. If it ain't broke, don't fix it.

>
frm2.Show();
}
////////// END OF PARTIAL CLASS FORM1 : Form
// start of Partial Class Form 2: Form
namespace MDIForms
{
public partial class Form2 : Form
{
Class2 myClass2;
Class1 myNewClass1;
public Form2() //default constructor not used
{
InitializeCompo nent();
myClass2 = new Class2();
myNewClass1 = new Class1(99, "new!Class1!!") ;
}
public Form2(Class1 passClass1, Class2 passClass2)
{

Interesting that you're not calling InitializeCompo nent() (or
explicitly calling "this()" as a constructor initializer). Of course,
you haven't shown what Form2 actually does, but you'll find that if you
put some controls on it in the designer, those *won't* be seen when the
form is displayed by Form1.clikMeNew FToolStripMenuI tem_Click.
I did add InitializeCompo nent() in the parametric form, but I
accidentally deleted it when I posted the (incomplete) code in my
haste to make it more readable. Sorry.
>
myClass2 = passClass2;
myNewClass1 = passClass1;
}
// end of Partial Class Form 2: Form
Discussion: classes 1,2 are simple classes, that contain a public
int
and public string as members, declared OUTSIDE the Form1 class, and
are not nested to the Form1 class, nor is Form 2 inherited from
Form1, but the important point is that in C# there is 'hiding' of
previously declared classes.

Nope, the classes aren't hidden at all. To prove it, just write:

new Class1(0, "");
new Class2();

in the constructor. Obviously it won't do a lot of good (unless those
constructors do interesting things) but the fact that it compiles
proves that the classes aren't hidden.
OK, thanks for that terminology. Hiding is not the best word, perhaps
'local variable overriding of outer scope (?) variables of the same
name'. Or something like that. OK I got it. Or maybe not. Moving
right along...
>
You *could* effectively hide them (so they'd need to be referenced in a
more explicit way, e.g. with the "global" namespace alias) by genuinely
declaring Class1 and Class2 inside Form1, e.g.

public partial class Form1 : Form
{
class Class1 {}
class Class2 {}

Class1 myClass1; //cannot comment out this line--compile error
Class2 mYClass2;

// Code as before

At that point variables myClass1 and mYClass2 would refer to the nested
classes; the constructor call to Class1 within the Form1 constructor
wouldn't compile as the appropriate constructor signature hasn't been
declared, and clikMeNewFToolS tripMenuItem_Cl ick wouldn't compile
because the types of the Form2 constructor call would be incompatible.
Interesting, thanks. You left out an important detail--when there is
ambiguity, how can you tell the compiler to 'override' the ambiguity
and compile? In C# there is no easy way, for example, if the Class1
and Class2 variables are in namespace XYZABC, you can maybe write
XYZABC.Class1 myClass1; etc., but everytime I tried this it doesn't
compile (Update: I see the 'this' pointer below solves some
ambiguity)
This is illustrated by the line //
Class1 myClass1 = new Class1(100, "heLlO1YouTube! "); //HIDES or
'overrides' previous declaration!

That's not hiding a class. That's hiding an instance variable with a
local variable.
OK, terminology noted, thanks.
>
{Jon would argue this is imprecise terminology: it's "declaring a
variable called myClass0, of *type* Class0.", and would then point out
that "hiding" is an imprecise word to use, since you are declaring and
defining and instantiating a new local variable that has the same name
as the variable "myClass0".

Hiding is a perfectly fine word to use - but saying you're declaring a
class when you're actually declaring a variable is hugely misleading.
OK, noted. If this is in your book I'll study it, but likely if not
I'll forget it five minutes after I post this thread.
>
Feel free. If you see me make a mistake, I'll welcome the correction.
Every computer science book--and even the good ones--have errors, so I
appreciate your modesty.
>
Even though myClass1 is declared outside the default constructor of
Form1, it is 'overridden' (I am using imprecise terminology, but if
you're astute you will understand the problem) by the second
declaration of myClass1 inside the default constructor of Form 1.

Indeed. Although you could still access it as "this.myClass1" . If you
change this line:
myClass1 = new Class1(100, "heLlO1YouTube! ");
to
this.myClass1 = new Class1(100, "heLlO1YouTube! ");

in the Form1 constructor and uncomment this line:
Class1 myClass1 = new Class1(100, "heLlO1YouTube! ");

then the program will work without a NullReferenceEx ception.
Wow! You're good. I played around and see what you're talking about,
even though I'm not 100% clear on why the 'this' pointer (the object
calling 'Form1()') makes such a difference, but maybe the object/
variable understand to use the 'outermost' Class1. Leaving out the
'this' pointer did give a nice compiler warning CS0136, which, had I
seen it before, would have obviated having to write this entire thread
(though I guess I would not have learned as much).

// here is what I played with, comments from compiler and hoving
ToolTips

this.myClass1 = new Class1(100, "heLlO1YouTube! "); //Class1
Form1.myClass1

//failure to use 'this' above gives a compiler error: error CS0136: A
local variable named 'myClass1' cannot be declared in this scope
because it would give a different meaning to 'myClass1', which is
already used in a 'parent or current' scope to denote something else

Class1 myClass1 = new Class1(100, "FUYouTube! ");//equivalent to class
MDIForms.Form1 (local only)
//never used since local and goes out of scope

// end of playing

>
And, using this 'wrong' way, you will get a null reference passed to
Form2, which is not correct.
And, commenting out the line "Class1 myClass1; //cannot comment out
this line--compile error" is even worse--you will get a compile error
rather than a runtime error, since myClass1 inside the normal default
constructor of Form1 will be treated as a local variable that cannot
be seen elsewhere.

Indeed, although I'd argue that a compile-time error is *better* rather
than an execution time error. If we wanted to leave all errors until
execution time, we'd use a dynamic language...
OK.
>
If you understand this simple example you're half way towards
understanding the problem in this thread. {assuming you even care
about understanding the problem rather than pushing your own agenda}

Your simple example doesn't show anything that couldn't be more easily
shown in a complete console app.
Assuming I knew what the problem was.

Thanks for your analysis. I will buy your book and hope to catch you
later in another thread...

RL
Jul 23 '08 #10

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

Similar topics

0
3321
by: Zlatko Matiæ | last post by:
Hi everybody! Recently I was struggling with client/server issues in MS Access/PostgreSQL combination. Although Access is intuitive and easy to use desktop database solution, many problems appear when someone is trying to use it as front-end for real server database systems such as PostgreSQL or MySQL. One of these problems is regarding pass-through queries and parameters. I wanted to have all the code on client, while executing it on...
3
25283
by: Todd Schinell | last post by:
Back in July, Jeffery Tan posted this: http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=OWOTdf0VDHA.2296%40cpmsftngxa06.phx.gbl In response as to how to get click events from a user control to invoke a method in the parent form. This code doesn't seem to work for me, I've tried it a number of times with very simple test cases (A user control with a single button and a parent form with a single text box) and it always...
8
3364
by: Brian F | last post by:
Exactly what the subject says. I have an ASP page that I want my C# windows application to open in Internet Explorer, and if possible have it send along a list of values from a list box. Thank you.
5
11826
by: Jason Huang | last post by:
Hi, In Global.cs, I have public string myString="". Another 2 forms are Form1.cs, Form2.cs. How do I use the Global.cs' myString to store a string in Form1 and then pass to Form2? Thanks for help. Jason
6
5349
by: juky | last post by:
Hi all, I have 2 applications one in VB.net and the other in VC6. I need to pass data between them. How can I do it? what's the best way to implement such communication ? Any comment will be appreciate. Thank you. Juky
3
8669
by: swb76 | last post by:
I have a Object Oriented question. I got two forms - Form1 and Form2. I also got two classes Class1 and Class2 Form1 has objects Object1 - instance of Class1 and Object2 - instance of Class2. When i load Form1, i load this form and instantiate Object1 and Object2. Please note Object1 and Object2 can be fairly large because of several variables.
3
4027
by: forest demon | last post by:
for example, let's say I do something like, System.Diagnostics.Process.Start("notepad.exe","sample.txt"); if the user does a SaveAs (in notepad), how can i capture the path that the user selects? thanks...
4
2274
by: =?Utf-8?B?bmlja25hbWU=?= | last post by:
I have the following xml Schema: “<?xml version="1.0" encoding="Windows-1252"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="Document"> <xs:complexType> <xs:sequence> </xs:sequence> <xs:attribute name="name" type="xs:string" />
12
2043
by: Nathan Sokalski | last post by:
I have several CustomControls that I have written for my project. However, when I try to compile I recieve the following warning & errors: Warning 32 Could not resolve this reference. Could not locate the assembly "nathansokalski_com_test, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL". Check to make sure the assembly exists on disk. If this reference is required by your code, you may get compilation errors....
0
8801
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
8707
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
9314
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9174
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9015
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...
0
7953
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4464
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...
1
3158
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
2520
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.