By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,011 Members | 2,968 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,011 IT Pros & Developers. It's quick & easy.

How to pass information, classes between forms in Windows Applicationmode

P: n/a

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
"clikMeButton2BringUpANew_Child_Form_to_The_MainFo rm_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
clikMeButton2BringUpANew_Child_Form_to_The_MainFor m_Click(object
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_exists_in_Form2 = passClass1_from_Form1; //
names are arbitrary of course

InitializeComponent();

// 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()
{
InitializeComponent(); //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.AutoValidate =
AutoValidate.EnableAllowFocusChange; //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
Share this Question
Share on Google+
12 Replies


P: n/a
raylopez99 <ra********@yahoo.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
"information 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.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 21 '08 #2

P: n/a
On Jul 21, 1:34*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
raylopez99 <raylope...@yahoo.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
"information 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

P: n/a
raylopez99 <ra********@yahoo.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.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 22 '08 #4

P: n/a
On Jul 22, 5:12*am, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
raylopez99 <raylope...@yahoo.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_exists_in_Form2 = passClass1_from_Form1; //
names are arbitrary of course
InitializeComponent();
// 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_exists_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...timeout 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 refMethodChangeClass2 (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;
InitializeComponent();

}

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 refMethodChangeClass2 (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.interger02 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 "myForm1Class2" 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 "surprisingly" 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;
//Works3DerivedClass = 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;
Works3DerivedClass = new Class3();
Works3DerivedClass = passClass3;
InitializeComponent();
}
// 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 refMethodChangeClass2 (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

P: n/a
raylopez99 <ra********@yahoo.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_exists_in_Form2 = passClass1_from_Form1; //
names are arbitrary of course
InitializeComponent();
// 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_exists_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...timeout 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 refMethodChangeClass2 (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.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 22 '08 #6

P: n/a
On Jul 22, 11:54 am, Jon Skeet [C# MVP] <sk...@pobox.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? 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_exists_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()
{

InitializeComponent();

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

}

private void clikMeNewFToolStripMenuItem_Click(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;

InitializeComponent();

}

private void button1_Click(object 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

P: n/a
raylopez99 <ra********@yahoo.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_exists_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.privateVariable = "private";
new Nested().ShowPrivateVariable(t);
}

class Nested
{
internal void ShowPrivateVariable(Test t)
{
Console.WriteLine(t.privateVariable);
}
}

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.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 22 '08 #8

P: n/a
raylopez99 <ra********@yahoo.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.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Jul 23 '08 #9

P: n/a
On Jul 23, 12:56 pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
raylopez99 <raylope...@yahoo.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()
{
InitializeComponent();
// 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=something;) 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
{
InitializeComponent();
myClass2 = new Class2();
myNewClass1 = new Class1(99, "new!Class1!!");
}
public Form2(Class1 passClass1, Class2 passClass2)
{

Interesting that you're not calling InitializeComponent() (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.clikMeNewFToolStripMenuItem_Click.
I did add InitializeComponent() 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 clikMeNewFToolStripMenuItem_Click 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 NullReferenceException.
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

P: n/a
On Jul 23, 11:40 pm, raylopez99 <raylope...@yahoo.comwrote:
raylopez99 <raylope...@yahoo.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'm glad.
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.
It really makes a huge difference. Apart from anything else, if you
can come up with a short, complete example you can cut and paste *all*
of it into a post, avoiding any spurious changes.
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.
In a WinForms app generated by Visual Studio, it's in Program.cs.
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.
If all you meant was that you wanted to see the Main method in a
different class, that would have been fine. It was your complaint that
it was "nested" in a class which was odd.
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?
Not really. It's quite a simple transformation, if you're not actually
using any WinForms code. In fact, you could just have deleted the
designer files, deleted the calls to InitializeComponent, made the
classes not derive from Form, and then change Program.cs to call a
method within your class instead of running Application.Run.

If you'd explained that you were having trouble doing the conversion,
I'd have helped with that - but instead you insisted that everything
was different in WinForms apps.

<snip>
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.
No, that's really not how it works. Being able to demonstrate
something in a console app really doesn't take much knowledge. If
console apps effectively scare you, it's well worth writing some.
They're a lot easier to work with than WinForms apps when you don't
actually need a GUI. For instance, displaying information is just a
matter of calling Console.WriteLine instead of fiddling around with
message boxes etc.

I strongly recommend that you play around with them a bit. One hint:
put a call to Console.ReadLine() at the end of your Main method so you
can see what's happened before the program terminates. (I don't do
this for my simple console apps usually because I build and run them
from the command line, where it's not an issue. It's really just in
Visual Studio.)

<snip>
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.
Then review the posts! There's not much point in me telling you
something if you completely ignore it and forget it. Learning the
right terminology is a vital part of learning how to communicate about
a programming language. Imagine if you were trying to learn English
grammar, but you kept calling nouns verbs... it would make everything
terribly confusing.
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...
Yes, and you were referring to it there - near the bottom. You also
referred to it in the event handling method - sorry that I didn't
mention that as well.
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
It still needs to be within a class declaration for Form1 - but you
could have moved it to just before the end of the class, e.g. after
the event handling method.
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=something;) and gives the intended result, unlike my
commented out code.
Yup. Using "this.myClass1" means "I want to refer to the instance
variable myClass1 belonging to "this" object, instead of a local
variable which happens to also have the name myClass1.
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
Avoid code like that. Setting a local variable to null at the end of
the method has no effect, and certainly doesn't trigger garbage
collection. In fact the object could have been collected before that
line of code, if nothing else references it.

(There are some situations involving captured variables where setting
a local variable to null *would* have an effect - probably an
unintended one - but that's a more complication situation. I mention
it only for completeness.)
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
<snip>

Certainly using a constructor this way is fine. Aside from anything
else, it's vital if you want to make the type immutable, which is
often a good thing.
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...
No, "hiding" is the right word - it's class that was the wrong word.
The local variable certainly wasn't *overriding* the instance variable
- that would suggest some kind of odd local polymorphism. If you don't
like the word "hiding" then "shadowing" is also fine.
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 clikMeNewFToolStripMenuItem_Click 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" will solve it to refer to variables, but if there's ambiguity
in the class names themselves, using the namespace is usually enough
to fix it. If it's still not (and there can be times where it's not
enough) you can use global::Namespace.Goes.Here.Classname

If that's *still* not enough (because you're referring to two types
which have the same fully qualified name but are in different
assemblies) you can use extern aliases - but try not to :)
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.
This kind of thing isn't in my book, I'm afraid - my book is aimed at
people who already know C# 1 reasonably well. Hopefully I *use*
terminology accurately though, so it's possible that it'll sink in by
osmosis :)

(If you've already got C# 3.0 in a Nutshell then I'd stick with that
until you're reasonably comfortable with the C# 1 features. It's a
good book. If you want a bit more of a "deep dive" into the C# 2 and 3
features, that's when my book would be helpful.)

<snip>
then the program will work without a NullReferenceException.

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).
Hopefully my explanation of the use of "this" above explained the
matter, but let me know if you want more detail (and a sample app :)
// here is what I played with, comments from compiler and hoving
ToolTips

this.myClass1 = new Class1(100, "heLlO1YouTube!"); //Class1
Form1.myClass1
Yup.
//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
I think you've got different code again then - because you'd normally
only see that if you had multiple scopes within the method, and
declared the variable twice within those scopes. For instance:

class ScopeDemo
{
int variable; // Instance variable

public void Method()
{
// Local variable - hides or shadows the instance variable
int variable;

{ // Create a new scope
// Declare another local variable - this causes CS0136
int variable;
}
}
}

// Class with Main in just so we can compile as a console app.
// Actually running this app does nothing. We could have
// removed this class and compiled as a class library instead.
class Test
{
static void Main() {}
}

That will generate CS0136. If you remove either of the local variable
declarations, it will compile. There will be warnings because we're
not actually *using* the variable, but it's only when there are
multiple local variable declarations that you see CS0136 - and that
would occur even without the instance variable existing at all.

Hope that helps,
Jon
Jul 24 '08 #11

P: n/a
On Jul 24, 1:58*pm, raylopez99 <raylope...@yahoo.comwrote:

<big snip - glad it was useful>
All in all, this thread reinforced my prejudice that you should stick
to canonical ways of building programs--learned through trial and
error--rather than understand, as you apparently have, the inner
workings of the C# language. *Unless you plan to write a book on C#.
Hmm. Each to their own I guess, but I personally would really hate
trying to code in a language which I didn't really understand.

Fortunately Eric Lippert has written about this in a much more
eloquent way than I can:
http://blogs.msdn.com/EricLippert/ar.../01/82168.aspx

Jon
Jul 24 '08 #12

P: n/a
On Jul 25, 11:50*am, raylopez99 <raylope...@yahoo.comwrote:
I do understand the C# code, not like you understand it, but enough to
write a decent program in console mode
I don't want to sound patronising, and I know I will anyway, but: you
really can't know how well you understand something unless either you
created it in the first place, or you've explored so much of it that
you're aware of how much more there is.

Per my geneology console mode program in C#, I wrote a program that
works, because it proved a theorem that was proved (by hand) over 100
years ago. *So obviously the program is 'working'. *That said, if I
ran it through a profiler I'm sure I would find bottlenecks that could
be eliminated to make the program run even faster. *So there's various
degrees of success in the statement "my program works".
I don't claim that your program doesn't work. It may work very well
indeed. That's not the same as saying you understand it.
I would personally view some of the issues of understanding that you've
demonstrated (and corrected, mind you!) in this thread and a couple of
others as quite fundamental - certainly things I would expect even a
reasonably junior professional coder to understand. I know you're
learning C# as a hobby rather than for a career, and that's great - but
you shouldn't kid yourself that you understand C# yet.

I beg to differ. *I do understand C#, for one thing it doesn't have a
copy constructor like C++, because it passes references to references
or somesuch, probably 'virtually' behind the scenes, but I also
understand how to write a program in C#--not as well as you--but it
works (see above).
That shows you understand *some* C# - enough to get that particular
program written. It doesn't mean you understand C# "in general" or
that your grasp is deep enough to cope when faced with unexpected
behaviour.

<snip>
But at the same time I *do* think it's important at least for
*professional* coders to have a greater understanding of the language
than many do. It shouldn't be black magic. You shouldn't have to guess
what a line of code means, and you certainly shouldn't need to "try it
and see if it compiles" (with the exception of a few bits of type
inference, where that's far quicker than trying to go through the same
process that the compiler would).

But your standard is too high. *And at some level you need commented
code--I'm sure you've seen the example where a programmer is using
obscure syntax and code to say "Hello World!" but it's indecipherable
(done as a joke).
Absolutely, and that's a really bad idea. You certainly should write
the clearest code possible. Whenever I find myself writing "clever"
code, it's almost always the wrong thing to do.
This really applies more to professional coders than hobbyists, but
I've seen (and rejected) a depressing number of interview candidates
who claim to have years of experience, but clearly don't know the
language to any sort of reasonable level.

Your standards are too high. *Do you think India and China have so
many software engineers (and engineers in general) because they have
smarter people than the West? *Or maybe they study the hard sciences
more? *Or, it is because they lower their standards? (it's the latter,
from what I've read from people who know). *Yet they get the job done,
without really "knowing why".
Then they're building up technical debt. It's very easy to rush
products out of the door without knowing how they work. You then pay
for it when you can't make any changes, and when you can't find bugs.

The difference in productivity between someone who understands the
tools they're working with and someone who is just cutting and pasting
from web pages which claim to have snippets of code doing roughly
what's required is *massive*.
>*Ditto for doctors in China--they were
and are mostly technicians, that's why they cannot practice in the USA
easily, since the standards are higher there. *BTW even Scientific
American had an article a few years or decade ago about this issue--
software engineering is too complicated, standards for coding are too
high, take too long to learn, too many bugs (memory leaks anyone?)--
hence (not in the article, but by implication) the "Visual Studio
Wizard" as a step forward, though it is derived originally from the
less capable language of Visual Basic.
Too many bugs and memory leaks you say - now why do you think that is?
That's not because the standards are too *high* - it's because they're
too *low*. When people don't know what they're doing, of course
they'll create bugs.

Now, I'm all for making things simpler, so there's less that people
*do* need to know - and C# is a much simpler language than C++, for
instance. That doesn't mean that a professional coder should feel
comfortable if they don't know what they're doing. For hobbyists it's
somewhat different, but if someone's going to pay you to write code,
you should know what that code means.

Jon
Jul 25 '08 #13

This discussion thread is closed

Replies have been disabled for this discussion.