Re: How to pass information, classes between forms in Windows Application mode



raylopez99 <raylopez99@xxxxxxxxx> wrote:
In that case I guess it's the end of the discussion.

That's right. You haven't been as helpful as before, I suspect because
you don't like to reply to me, and also because you don't understand
the newbie concerns I had. I particular, as per my last post, I
pointed out why these errors occurred, and how to correct them
(reproduced below) But you refuse to comment because I suspect you
feel this is beneath you (assuming, charitably, you even are aware of
these problems--it's quite possible that because your coding style is
different and you deal with console mode, you never even come across
this problem, and perhaps you're not even aware of this problem)..

I tend to use console programs to show short but complete examples,
because they allow me to focus on the language features without getting
bogged down by unnecessary clutter. However, I've written code for
various types of apps - console, WinForms, WPF, ASP.NET web apps, and
ASP.NET web services. (Not WCF yet... one day.)

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.

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.

The issue is
'entry points' and you surprised me by even acknowledging you know
what this term means, since it's kind of obscure. I expected you would
say 'define entry point'.

It's really not that obscure, and it's not like I'm new to C# and .NET.

Please show who you could possibly have the Main method *not* in a
class or struct.

Not the issue. The issue is having Main inside a class, as is often
done with console examples (I like the old style--main being outside
with the classes inside it--do you even know what that old style is?
LOL).

But my point is that Main is *always* within a class (or struct,
although I've never seen that in real code) whether it's a console app
or a WinForms app. Your wrote:

<quote>
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
</quote>

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.

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.

OK, fine. FYI you might want to examine the sample code I provide
below, and convince yourself it will not work properly unless the
conventions I clearly outline below are followed. Then, in your own
words, point out why you think so--feel free to use all the fancy two-
bit words you can think of.

See below. It's still not a complete example though, whereas you could
very easily have posted a complete example which shows all the same
points.

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.

But what question are you looking for? I've outlined the scenario
below. Study it and convince yourself. If you need a complete
example to understand what is happening below, you are a poor
programmer for sure.

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.

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 from
http://manning.com/skeet

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.

Oh, I see. You claim to "understand everything" yet you fail to tell
us what you understand, and give the impression of being a troll and
newbie. I will be charitable and assume you're just yanking my chain
and don't expect to ever answer any question or make any comment,
other than harp about proper terminology. But to be unkind I could
suspect you don't know what you're talking about. In the future, I'll
have to examine what you say more closely, as it might be completely
wrong. Perhaps you're not the expert I assumed you were, if you don't
even understand and cannot comment on the below program.

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.

If you'd post a complete program which either you believe goes against
something I've said,

What did you say? Nothing of much importance, except be sure to use
the right words when describing a problem. But this assumes you even
recognize a problem exists, which in this thread you have not.

I've recognised that you have an issue in terms of your understanding
of scope, access and what you're actually declaring.

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

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.

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

//instead, use this...
myClass1 = new Class1(100, "heLlO1YouTube!");
mYClass2 = new Class2(69, "hello2FooTUbE!");
}

private void clikMeNewFToolStripMenuItem_Click(object sender,
EventArgs e) //<--Jon, are you confused as to what
"clikMeNewFToolStripMenuItem_Click" method does, and do you understand
why it's not important?

No, but I still believe it's better to give people code they can
compile and run instead of partial information.

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

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


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.

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.

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.

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.

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

I think. But he would not understand
this until AFTER I had figured out an answer to my own question,
largely because Jon either, because of convention, never makes these
kind of newbie mistakes (he follows a template that has shielded him
from these mistakes, codes largely in Main where such mistakes are
easier to spot, or, charitably, he is just being an ass in this
thread. I think perhaps it's the last reason but maybe it's the
former--does Jon Skeet know what he's talking about? I'll have to
check his posts more carefully in the future.}

Feel free. If you see me make a mistake, I'll welcome the correction.

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.

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

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.

--
Jon Skeet - <skeet@xxxxxxxxx>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
.