How to pass information, classes between forms in Windows Applicationmode

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • raylopez99

    How to pass information, classes between forms in Windows Applicationmode


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

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

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

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

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

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

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

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

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

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

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

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

    InitializeCompo nent();

    // other stuff here if you want
    }

    Done.

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

    public partial class Form1 : Form
    {
    Class1 myClass1; //Note where this is located! outside the
    default constructor for Form1
    // this is called a 'forward reference' in C++, and you need to do
    this for C# as well


    public Form1()
    {
    InitializeCompo nent(); //mandatory for all forms, stuff
    that the Wizard fills and I don't fool with

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

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

    }

    /// other stuff here

    }

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

    RL


  • Jon Skeet [C# MVP]

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

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

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

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

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

    Comment

    • raylopez99

      #3
      Re: How to pass information, classes between forms in WindowsApplicat ion mode

      On Jul 21, 1:34 pm, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
      raylopez99 <raylope...@yah oo.comwrote:
      Keywords: scope resolution, passing classes between parent and child
      forms, parameter constructor method, normal constructor, default
      constructor, forward reference, sharing classes between forms.
      >
      Here is a newbie mistake that I found myself doing (as a newbie), and
      that even a master programmer, the guru of this forum, Jon Skeet,
      missed! (He knows this I'm sure, but just didn't think this was my
      problem; LOL, I am needling him)
      >
      I still don't think it's your problem. You're still confused - and
      what's more you've changed the problem from "accessing a variable" to
      "informatio n passing".
      Nope. That was my problem. My problem was that I could not even see
      the class1 in Form2 and now it's solved. Your problem (in your mind's
      eye) is another problem altogether.

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

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

      You remind me of the college professor who lost his keys in the dark,
      and kept vainly looking under a street lamp far away from where he
      lost them. When asked if he found the keys, he replied, "well, I
      didn't lose my keys here, but this is the only place I know that has
      light!" LOL, that's you Jon. You're answering a question that I didn't
      pose (or perhaps I did pose, 'in your mind's eye'?).
      >
      The point being:  you need a forward reference if the Class1 is not
      'nested' in the Form1 {}, that is, if Class1 is part of a separate
      translation unit or module, even if Class1 is in the same namespace as
      Form1.
      >
      No. There is no such thing as a forward reference in C#, and what you
      seem to think is a forward reference is actually just a variable
      declaration.
      OK, let's call the forward declaration a 'variable declaration'. A
      rose by any other name...

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

      RL

      Comment

      • Jon Skeet [C# MVP]

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

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

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

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

        Comment

        • raylopez99

          #5
          Re: How to pass information, classes between forms in WindowsApplicat ion mode

          On Jul 22, 5:12 am, Jon Skeet [C# MVP] <sk...@pobox.co mwrote:
          raylopez99 <raylope...@yah oo.comwrote:
          And accessing another type's variables has nothing to do with my
          problem, whether you acknowledge it or not.
          >
          It has everything to do with the problem you originally described,
          which had one form inheriting from another. However, when you came to
          show actually code your forms were both inheriting from Form.
          >
          BTW, all my variables
          were set public and still the code did not work until I hit upon the
          parameterised constructor.
          >
          Indeed, because your code wasn't how you originally described it. You
          claimed an inheritance relationship which simply wasn't there.
          Yes, it's true, I did have three different problems, because before
          hitting upon the solution, which was the parametrical constructor, I
          tried various things like setting Form2:Form1.

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

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

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

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

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

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

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

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

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

          }

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

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

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

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

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

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

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

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

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

          myClass2 = new Class2();
          myClass2 = passClass2;
          myNewClass1 = new Class1();
          myNewClass1 = passClass1;
          Works3DerivedCl ass = new Class3();
          Works3DerivedCl ass = passClass3;
          InitializeCompo nent();
          }


          // end of example ***3***

          //Start of example **1**

          **1**


          public class Class2
          {

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

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


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

          }

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

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

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

          }

          // end of example **1**
          You can too.  Using the public properties Get and Set, you certainly
          can refer to the Form1.myClass1 variables, even private variables, and
          I demonstrated this in my code to my satisfaction.  Would you like to
          see a copy?  Just open any textbook on C# and look under "Get" and
          "Set" for Properties.
          >
          That's not referring to the variables. That's referring to the
          properties, which happen to the return the current variable value. Big
          difference. Try passing the property by reference, for example...
          >
          OK, fine, I agree. Different issue, yes, you're right here, and so
          was I, but we're talking different stuff, like you acknowledge.

          You remind me of the college professor who lost his keys in the dark,
          and kept vainly looking under a street lamp far away from where he
          lost them.  When asked if he found the keys, he replied, "well, I
          didn't lose my keys here, but this is the only place I know that has
          light!" LOL, that's you Jon. You're answering a question that I didn't
          pose (or perhaps I did pose, 'in your mind's eye'?).
          >
          No, I'm answering the question you *did* pose, even though it may not
          have reflected reality. You repeatedly stated that the child form
          inherited from the parent form - but then your code showed otherwise.
          That's what confused me - I foolishly trusted that you were accurately
          describing your code.
          >
          So yes, I'll take part of the blame for not solving your problem
          earlier - but you should also accept your portion of it for
          misdescribing it in the first place.
          I was teasing you, a flame, nothing more. Both of us are "right",
          but, like the pig in Charlotte's Web, or was that Animal Farm, I'm
          more right...haha. Kidding. I take blame for switching the goal
          posts a bit, true.

          >
          The point being:  you need a forward reference if the Class1 is not
          'nested' in the Form1 {}, that is, if Class1 is part of a separate
          translation unit or module, even if Class1 is in the same namespaceas
          Form1.
          >
          No. There is no such thing as a forward reference in C#, and what you
          seem to think is a forward reference is actually just a variable
          declaration.
          >
          OK, let's call the forward declaration a 'variable declaration'.  A
          rose by any other name...
          >
          Um, no. A forward declaration in C++ is not the same thing as a
          variable declaration at all.
          OK, you win on this point. My bad. I'll call it a 'variable
          declaration' even though a class object is being declared, not a
          primitive data like int, double, etc, which I like to think as
          'variables' in my mind's eye.
          I enjoy teaching and
          coaching, which is why I participate here - but it's got to be a two-
          way process.
          >
          I appreciate your help, even though I like to flame as you can tell.
          Comes from being anonymous (which I'm not entirely, since a few people
          in the real world know who I am under this name, my old boss for
          example, but for the most part I'm anonymous). Of course I learn a
          lot just trying to prove stuff, even just now I wasted an hour of my
          life but learned something new, as per the above.

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

          RL

          Comment

          • Jon Skeet [C# MVP]

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

            raylopez99 <raylopez99@yah oo.comwrote:
            Indeed, because your code wasn't how you originally described it. You
            claimed an inheritance relationship which simply wasn't there.
            >
            Yes, it's true, I did have three different problems, because before
            hitting upon the solution, which was the parametrical constructor, I
            tried various things like setting Form2:Form1.
            >
            BTW, I don't think setting Form2 to inherit from Form1 will solve the
            problem without the use of a parametrical constructor, as I thought I
            tried this, but maybe it will--time to do a quick test of this thesis
            before I post...time out while I check this...making sure all
            variables are public in both the base class and derived class... OK,
            after many permutations, I confirm you cannot "see" any derived class
            in Form 2 that's been instantiated in Form1, either, whether or not
            Form2: Form1 or Form2: Form, unless you pass the derived class in the
            parametized constructor, just like I said in this thread.
            If Form2 : Form1, then from Form2 you will be able to see any variables
            in Form1 which are declared as public or protected (or internal if
            they're in the same assembly).
            Just passing a parameter doesn't mean that Form2 is magically able to
            see Form1.myClass1. Form2's constructor will be able to see the
            parameter, which starts off with the same value as Form1.myClass1, but
            you can't actually refer to the Form1.myClass1 variable from Form2.
            >
            I think we're talking two different things. If, referring to this
            passage:
            >
            (#1) And just to make the point clearer, Form2 must have as a
            constructor something besides the normal (default) non parameter
            constructor, along these lines:
            >
            public Form2(Class1 passClass1_from _Form1)
            {
            myClass2_that_e xists_in_Form2 = passClass1_from _Form1; //
            names are arbitrary of course
            InitializeCompo nent();
            // other stuff here if you want
            }
            Alternatively, Form2 could have a parameterless constructor and you
            could set properties, or call methods to pass it the information.
            Constructors aren't the only way to pass information between objects.
            I'm not entirely sure you're correct [UPDATE: after running the tests
            below, I'm sure that a person--not you--but a person who says an
            object that is passed to Form2 using the parametric constructor of
            Form2 from Form1 is not passing the true object but a copy of the
            object is not correct]
            You're neither passing "the true object" nor a copy of the object.
            You're passing a reference to the object.
            if you say myClass2_that_e xists_in_Form2 cannot
            "actually refer to the Form1.myClass1 'variable' from Form2, since we
            are passing by value, so it must refer to it.
            No, not at all. You have passed the current value of the variable as
            the argument. If you change the value of Form1.myClass1, there will be
            no way for Form2 to retrieve it. It doesn't have access to the
            *variable*.
            But I think you're
            trying to say [THIS IS WHAT I TESTED BELOW--IT MAY NOT BE WHAT YOU
            WERE SAYING, BUT IT WAS INTERESTING FOR ME--RL] it cannot permanently
            change the variables (let's assume they are all public) in
            Form1.myClass1 since we are not using the 'ref' keywords to pass by
            reference.
            Passing by reference would effectively give temporary (i.e. duration of
            the constructor) access to the variable, yes. However, you can't take
            an arbitrary reference to an instance of Form1 and access its myClass1
            variable from Form2, while the variable is private.
            But, as we know, if you add the "ref" keyword, and with a
            helper function we can change a class (we can put the helper function
            in another class, or as a standalone function, that accepts 'ref
            Class2'), however, the issue here is (and this may or may not be what
            you have in mind) whether to use the above example
            "myClass2_that_ exists_in_Form2 " can permanently change any public
            variable in class "passClass2[1]_from_Form1", via changes made in
            Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]
            Reference parameters do effectively change the situation somewhat, but
            it's important to note that Form2 doesn't really know that it's
            Form1.myClass1 that's been passed to it by reference. It could be a
            local variable, or a variable from something completely different.
            There's only one way to find out, and that's to test this
            hypothesis...ti meout while I test this...I will pass a 'myClass2' from
            Form1 to Form2, using the parametric constructor, then change a public
            variable of myClass2 in Form2, then see if it's changed when I go back
            to Form1...the hypothesis being tested is that it's probably true that
            no change will be made to the Form1 'myclass' [UPDATE: AND THIS
            'HYPOTHESIS' IS WRONG-RL]--but let's see...
            >
            Ah, OK, about 60 minutes later...found out you're WRONG AGAIN JONNY!!!
            AHAHAHAHA. Hey just kidding, we're talking (I hope) about two
            different things.
            >
            Here's what I did, which probably will meet with an objection or two,
            but here goes: in Form1 I instantiated two classes, class 2 [call it
            "OriginalClass2 "], and class 3, see below at **1**. Class 3 is a
            'helper' class that changes public variables in class 2 by two
            methods, one method that takes a 'ref' keyword (pass by ref) {public
            void refMethodChange Class2 (ref Class2 x)} and the other method,
            {noRefMETHODCl2 (Class2 y)}, that changes public variables in class 2
            by taking class 2 via pass-by-value, each method accepting a Class2
            object.
            <snip>

            Rather than me explaining reference parameters here, I suggest you read
            my article on them:
            Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.


            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 - <skeet@pobox.co m>
            Web site: http://www.pobox.com/~skeet
            Blog: http://www.msmvps.com/jon.skeet
            C# in Depth: http://csharpindepth.com

            Comment

            • raylopez99

              #7
              Re: How to pass information, classes between forms in WindowsApplicat ion mode

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

              I'm not entirely sure you're correct [UPDATE: after running the tests
              below, I'm sure that a person--not you--but a person who says an
              object that is passed to Form2 using the parametric constructor of
              Form2 from Form1 is not passing the true object but a copy of the
              object is not correct]
              >
              You're neither passing "the true object" nor a copy of the object.
              You're passing a reference to the object.
              Yes, because we're dealing with a managed language C#. Is that your
              point? OK. A small point but noted.
              >
              if you say myClass2_that_e xists_in_Form2 cannot
              "actually refer to the Form1.myClass1 'variable' from Form2, since we
              are passing by value, so it must refer to it.
              >
              No, not at all. You have passed the current value of the variable as
              the argument. If you change the value of Form1.myClass1, there will be
              no way for Form2 to retrieve it. It doesn't have access to the
              *variable*.
              Not true. You might have something else in mind. I am finding out
              that both in what I call the non-inherited model of Form1: Form and
              Form2: Form, where I use a parameterized constructor to pass the
              class2 that has the information in it, and the inhereited model of
              Form2: Form1, that you suggested, I am getting "data binding" between
              the two forms in both directions. That is, with one small, trivial
              bug exception that I discuss below with inherited controls, I am
              getting both the public variable arr2 of Class2 to 'update' in both
              the Form1 (parent) and Form2 (child) when I make a change to arr2 in
              either parent or child forms (Forms 1 or Form 2, respectively). That
              is data binding in both directions. It's working. The small
              exception? When I inherit forms, Form 2 gets all the controls from
              Form1 (which BTW is very confusing and I would never do this in
              practice, but it's just a demo), and because of some obscure way form
              controls are instantiated, or perhaps something else, when I try and
              update arr2 using the inherited child form control button (but not the
              parent form control button), I get an 'old' value. But this is a
              minor bug or rather just an inherited control problem, or some small
              thing. The main thing is that using my system or your system I am
              getting data binding in both directions.
              >
              But I think you're
              trying to say [THIS IS WHAT I TESTED BELOW--IT MAY NOT BE WHAT YOU
              WERE SAYING, BUT IT WAS INTERESTING FOR ME--RL] it cannot permanently
              change the variables (let's assume they are all public) in
              Form1.myClass1 since we are not using the 'ref' keywords to pass by
              reference.
              >
              Passing by reference would effectively give temporary (i.e. duration of
              the constructor) access to the variable, yes.
              But, even using non-pass-by-reference or pass-by-value, I'm getting
              data binding in both directions, between parent and child (forms 1 and
              2), like I said above. Even with pass-by-value when you change the
              arr2[0] element of array arr2 in the child, the parent form shows it
              also being changed, and when you change it in the parent the child
              form class (which as a different name, but, we agree, it's the same
              reference to the same object) also changes. In short, data binding in
              both directions; it's working, insofar as I can tell.
              However, you can't take
              an arbitrary reference to an instance of Form1 and access its myClass1
              variable from Form2, while the variable is private.
              Yes. You keep saying this, and this is a newbie point well taken, but
              we (I) am beyond that. One funny thing I keep forgetting is that C#
              likes to always express access modifiers everywhere, with no access
              modifier being private by default. But for this example I set
              everything to public, using keyword 'public'. Everything, so this
              point is moot? (but see the note at the end here about 'class0')
              >
              But, as we know, if you add the "ref" keyword, and with a
              helper function we can change a class (we can put the helper function
              in another class, or as a standalone function, that accepts 'ref
              Class2'), however, the issue here is (and this may or may not be what
              you have in mind) whether to use the above example
              "myClass2_that_ exists_in_Form2 " can permanently change any public
              variable in class "passClass2[1]_from_Form1", via changes made in
              Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]
              >
              Reference parameters do effectively change the situation somewhat, but
              it's important to note that Form2 doesn't really know that it's
              Form1.myClass1 that's been passed to it by reference. It could be a
              local variable, or a variable from something completely different.
              It could be, but for some reason, like I said, when you change the
              parameter in Form 2, form Form1 is also updated, even when the forms
              are not inherited. If you feel this fact is shocking, unjustified,
              unexplained or whatever, let me know and I'll post the code. I think
              it's routine myself--just conventional data binding when you pass one
              class (or variable) to another. I'll tell you what I feel is
              shocking, below (keep reading--keyword 'class0' and 'nested classes').
              >
              <snip>
              >
              Rather than me explaining reference parameters here, I suggest you read
              my article on them:http://pobox.com/~skeet/csharp/parameters.html
              This is the article that I mentioned that I already have btw. It
              doesn't explain much for this forms example.
              >
              You still seem confused about the difference between passing a
              reference by value and passing a parameter *by* reference. Changing the
              *contents* of an object doesn't change the value of a variable which
              refers to that object.
              Agreed. So? I don't seem confused over that.
              >
              You should adjust your meaning of the word variable then. And no, a
              class *object* isn't being declared - a *variable* is being declared.
              Just because there's a variable doesn't mean any object is necessarily
              being created. The variable may have a null value, or refer to an
              object which was created elsewhere. For instance:
              >
              StringBuilder sb1 = new StringBuilder() ;
              StringBuilder sb2 = sb1;
              >
              That has declared two variables, but only one object has been created.
              Good point. I'll use variable then.

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

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

              namespace MDIForms
              {

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

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

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

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

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

              }


              public Form1()
              {

              InitializeCompo nent();

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

              }

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

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

              frm2.Show();
              }

              // NOW TURNING TO Form2:

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

              InitializeCompo nent();

              }

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

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

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

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

              (1) it must be nested within Form1

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

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

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

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

              RL

              Comment

              • Jon Skeet [C# MVP]

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

                raylopez99 <raylopez99@yah oo.comwrote:
                Alternatively, Form2 could have a parameterless constructor and you
                could set properties, or call methods to pass it the information.
                Constructors aren't the only way to pass information between objects.
                >
                What are the other ways?
                I just listed two: call a method, set a property. You mentioned some
                others yourself. My point is that your claim on the first message of
                this thread:

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

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

                Furthermore, the language itself really doesn't care about all of this
                - parameter passing, constructors etc remain consistent whatever you're
                doing (with some oddities around remoting and the like, admittedly).
                I'm not entirely sure you're correct [UPDATE: after running the tests
                below, I'm sure that a person--not you--but a person who says an
                object that is passed to Form2 using the parametric constructor of
                Form2 from Form1 is not passing the true object but a copy of the
                object is not correct]
                You're neither passing "the true object" nor a copy of the object.
                You're passing a reference to the object.
                >
                Yes, because we're dealing with a managed language C#. Is that your
                point? OK. A small point but noted.
                No, it's not a small point at all. It lies at the heart of what you're
                seeing when it comes to what you're calling data binding.
                if you say myClass2_that_e xists_in_Form2 cannot
                "actually refer to the Form1.myClass1 'variable' from Form2, since we
                are passing by value, so it must refer to it.
                No, not at all. You have passed the current value of the variable as
                the argument. If you change the value of Form1.myClass1, there will be
                no way for Form2 to retrieve it. It doesn't have access to the
                *variable*.
                >
                Not true. You might have something else in mind. I am finding out
                that both in what I call the non-inherited model of Form1: Form and
                Form2: Form, where I use a parameterized constructor to pass the
                class2 that has the information in it, and the inhereited model of
                Form2: Form1, that you suggested, I am getting "data binding" between
                the two forms in both directions.
                No, you're not. You can't make any changes to the *variable* of one of
                the forms. Sure, you can make changes to the object that the variable
                originally refers to, but you can't make the variable refer to a
                different object completely (unless you use a ref parameter to start
                with, of course - and then only during that call).
                That is, with one small, trivial
                bug exception that I discuss below with inherited controls, I am
                getting both the public variable arr2 of Class2 to 'update' in both
                the Form1 (parent) and Form2 (child) when I make a change to arr2 in
                either parent or child forms (Forms 1 or Form 2, respectively).
                Well, you haven't shown any code with a variable called arr2 in.
                However, I strongly *strongly* suspect that you're not changing the
                value of the variable - you're changing the contents of the array.

                Unless you have

                arr2 = [some value];

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

                arr2[0] = [some value];

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

                It's very important to understand the difference between a variable,
                its value, and the object it happens to refer to at a particular point
                in time.
                That
                is data binding in both directions. It's working. The small
                exception? When I inherit forms, Form 2 gets all the controls from
                Form1 (which BTW is very confusing and I would never do this in
                practice, but it's just a demo), and because of some obscure way form
                controls are instantiated, or perhaps something else, when I try and
                update arr2 using the inherited child form control button (but not the
                parent form control button), I get an 'old' value. But this is a
                minor bug or rather just an inherited control problem, or some small
                thing. The main thing is that using my system or your system I am
                getting data binding in both directions.
                Another use of incorrect terminology: data binding isn't what you think
                it is.
                However, you can't take
                an arbitrary reference to an instance of Form1 and access its myClass1
                variable from Form2, while the variable is private.
                >
                Yes. You keep saying this, and this is a newbie point well taken, but
                we (I) am beyond that. One funny thing I keep forgetting is that C#
                likes to always express access modifiers everywhere, with no access
                modifier being private by default. But for this example I set
                everything to public, using keyword 'public'. Everything, so this
                point is moot? (but see the note at the end here about 'class0')
                When the fields are public then yes, you can change the values of
                variables (so long as you have a reference to an instance of the
                containing class, of course).
                But, as we know, if you add the "ref" keyword, and with a
                helper function we can change a class (we can put the helper function
                in another class, or as a standalone function, that accepts 'ref
                Class2'), however, the issue here is (and this may or may not be what
                you have in mind) whether to use the above example
                "myClass2_that_ exists_in_Form2 " can permanently change any public
                variable in class "passClass2[1]_from_Form1", via changes made in
                Form2, rather than Form1. [CHANGED TO '2' from '1' to be consistent]
                Reference parameters do effectively change the situation somewhat, but
                it's important to note that Form2 doesn't really know that it's
                Form1.myClass1 that's been passed to it by reference. It could be a
                local variable, or a variable from something completely different.
                >
                It could be, but for some reason, like I said, when you change the
                parameter in Form 2, form Form1 is also updated, even when the forms
                are not inherited. If you feel this fact is shocking, unjustified,
                unexplained or whatever, let me know and I'll post the code. I think
                it's routine myself--just conventional data binding when you pass one
                class (or variable) to another. I'll tell you what I feel is
                shocking, below (keep reading--keyword 'class0' and 'nested classes').
                Yes, nested classes have access to private members in their enclosing
                class. That's not shocking to me, because it's part of the spec. As for
                the rest, it's a simple matter of understanding the difference between
                an object and a reference.
                Rather than me explaining reference parameters here, I suggest you read
                my article on them:http://pobox.com/~skeet/csharp/parameters.html
                >
                This is the article that I mentioned that I already have btw. It
                doesn't explain much for this forms example.
                Your forms example is still massively incomplete.
                You still seem confused about the difference between passing a
                reference by value and passing a parameter *by* reference. Changing the
                *contents* of an object doesn't change the value of a variable which
                refers to that object.
                >
                Agreed. So? I don't seem confused over that.
                Yes, you do. You keep claiming to be able to change the value of a
                variable you don't have access to, just because you can change the
                contents of the object that the variable happens to refer to. They're
                not the same thing.
                OK, here is what I found "shocking". I took your suggestion and for
                one version of this program I used inheritance, like I said above, as
                in Form1: Form and Form2: Form1 <--note the inheritance (the other
                version, which also works, uses two 'independent' forms Form1: Form
                and Form2: Form). Both the inherited and non-inherited versions use
                the parametricized constructor to pass classes 1 and 2, but,
                crucially, I added a third class, class 0, that was nested. This
                class 0 was nested and declared public (twice) within Form1, and thus
                could be 'seen' (by Intellisense, and ultimately by the program)
                unlike declared Classes 1 and 2 (using "Add" to the Solution), which
                had their own modules/translation units, unnested, outside of Form1.
                This is part of the problem - instead of trying to isolate one single
                piece of how the language behaves, you're coming up with massive
                examples with non-descriptive names (Class1, Class2, Class3, Form1,
                Form2) and making them *much* more complicated than they need to be.
                Why involve designer classes (which you never post), partial classes,
                inheritance *and* nested classes all in the same example? Stick to one
                at a time, preferably in a simple Console app which doesn't require any
                extra code. Your examples would be *much* clearer that way.

                Your code is even incomplete in the non-designer classes - you haven't
                shown where Form2 is declared.
                Specifically, consider 'nested' class 0 as follows, which is properly
                seen by base Form 1 and derived Form2. Comments //!! below
                >
                namespace MDIForms
                {
                >
                public partial class Form1 : Form
                {
                Class1 myClass1; //though these are public, do they now become
                'private' since no keyword public? That is the question!
                Class2 aNew2Class; // " "
                >
                public Class0 myClass0; // !! keyword 'public' required!!
                Shocking, no?!!
                Required to do what? To see it from Form2? No, it can be private. It
                can also be declared anywhere in the class, even after the nested
                class, contrary to your later assertion. Here's an example:

                using System;

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

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

                private string privateVariable ;
                }

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

                <snip incomplete code>
                Perhaps, and I could use your input, the problem 'earlier' in this
                thread is that classes 1 and 2, which are not nested, are not
                explictly declared prior to the Form1 contructor with the keyword
                'public', and, though in their respective modules I declare them as
                'public', this makes them 'private' somehow when declared within Form
                1 without the keyword 'public' (that is truly shocking if true).
                >
                Thanks for your help so far. I look forward to your reply.
                If you would post a short but *complete* program which demonstrates
                something strange.

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

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

                Comment

                • Jon Skeet [C# MVP]

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

                  raylopez99 <raylopez99@yah oo.comwrote:

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

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

                  Are you seeing a pattern?

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


                  (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 - <skeet@pobox.co m>
                  Web site: http://www.pobox.com/~skeet
                  Blog: http://www.msmvps.com/jon.skeet
                  C# in Depth: http://csharpindepth.com

                  Comment

                  • raylopez99

                    #10
                    Re: How to pass information, classes between forms in WindowsApplicat ion mode [ FINALLY!]

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

                    Including Main in a class isn't the same as creating a nested class -
                    and it's *always* in a class (or struct) so it's not a "convention " -
                    it's part of how you *have* to define methods.
                    Yes, but it doesn't address the issue of scope, etc. But let's move
                    on.
                    >
                    That's not declaring a class. That's declaring a variable called
                    myClass0, of *type* Class0. The sooner you understand that, the better.
                    Unless you use the "class" keyword, you're *not* declaring a class.
                    I need a complete program to make sure that I'm seeing exactly the same
                    effect as you. It's common to want to be able to reproduce an issue
                    before commenting on it. It's also common to want to see minimal code
                    that *does* reproduce an issue. Both of these are most easily achieved
                    with console apps, when the topics in question aren't inherently
                    related to GUIs - and the issues you've got here really, *really*
                    aren't GUI-specific.
                    But I wrote the program in Windows Form application mode, not console
                    mode. I could reproduce a Windows Form error in Console mode, I would
                    be quite the experienced programmer, no? I would know what the error
                    is, that it's not a Windows specific error, then I would write a
                    "Console mode" equivalent of the erroneous code, then I would post the
                    complete console mode code (that's erroneous) for you to comment upon
                    and find the solution to the error. Needless to say, this is absurd.
                    If I'm that competent a programmer, I would not need you or anybody
                    else to spot errors in my code; I would not make errors in the first
                    place.
                    >
                    And you wrote a book? What was it, self published?
                    >
                    I'm not going to start bragging about my book here. Suffice to say the
                    reviews are pretty positive so far. Look for yourself on amazon.com.
                    You might even want to read the free chapters which are available fromhttp://manning.com/skeet
                    This is a good book, an intermediate level book. Just took a look at
                    Chap. 6, about Iterators, and writing your own, which I just reviewed
                    a week or so ago online, with multiple 'yield return' statements and
                    the like. I probably will buy this book, it looks well done. I hate
                    beginner "Dummies" books, which are good but not enough depth at
                    times--you need a little meat, like those Scott Meyers books on
                    Effective C# from the late 1990s.
                    >
                    I understand everything that occurs in the C# language in this thread.
                    I don't understand some of what you're trying to communicate because
                    you persist in talking inaccurate terms (such as "forward references")
                    and posting incomplete programs.
                    OK, OK, I'm just a newbie. And I code for 'fun' --I have a real job.
                    >
                    While you fail to use correct terminology, even after being corrected
                    on it, communication is difficult. Likewise it is harder to comment on
                    a program when I'm only given half the code.
                    But your lingo is not conducive to the free flow of information. It's
                    like first having to repeat a magic number before I get an answer.
                    You told me the magic number five posts ago, but I forgot it.

                    I've recognised that you have an issue in terms of your understanding
                    of scope, access and what you're actually declaring.
                    Then say so. Do we need to get to this level of back and forth before
                    you comment? Finally, however, I see you do comment below. A belated
                    "thanks" I guess.
                    >
                    Study and commit to memory, I've added a few Easter Egg comments
                    tailored just for you Jon:
                    >
                    Here it is:
                    ////////// START OF PARTIAL CLASS FORM1: Form
                    public partial class Form1 : Form
                    {
                    Class1 myClass1; //cannot comment out this line--compile error
                    <--do you know why, Jon?
                    >
                    Obviously - you're referring to it in the constructor.
                    Really? A constructor in my "book" is the stuff that appears in public
                    Form1 () {//here}, but I guess I'm using the wrong lingo again.
                    Anyway, moving right along...
                    However, you could move the declaration to after the contructor and
                    methods - or even to a different file which also declares Form1 (again
                    as a public partial classs).
                    Oh, really? OK, I just tried this and it doesn't compile (sorry in
                    advance about the incomplete code, but you know how that goes)...

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

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

                    //////end

                    As you can see, the program did not compile. But I guess once again I
                    misunderstood, my apologies in advance. Moving right along...
                    >
                    Class2 mYClass2;
                    public Form1()
                    {
                    InitializeCompo nent();
                    // Class1 myClass1 = new Class1(100,
                    "heLlO1YouTube! "); //
                    HIDES or 'overrides' previous declaration! <--Jon, does this ring a
                    bell? Have you done this? If not, why not? Coding style perhaps?
                    >
                    It hides it, yes. I do it occasionally for parameters to constructors,
                    e.g.
                    >
                    public void Foo (int something)
                    {
                    this.something = something;
                    >
                    }
                    >
                    I try to avoid doing it in other cases, however.'
                    OK, I did get that, I think, as I understand the code fragment you
                    gave is perfectly legal (this.something =something; is not the same as
                    something=somet hing;) and gives the intended result, unlike my
                    commented out code.
                    >
                    //if you pass class as above rather than below line, you
                    get null pointer! -wrong!! <--Jon, do you understand why this is *not*
                    a null pointer, but a null reference, and why most people think that's
                    bad, regardless of what you call it?
                    >
                    The default value of a reference type non-local variable is null. As
                    for whether it's "bad" that depends on the context. Sometimes it's
                    exactly what you want - but not in this case.
                    Understood. I even saw in a Windows App event handler some code like:

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

                    >
                    "But give me complete code!" says Jon,
                    unaware that in Forms some of the complete code can run a few thousand
                    lines for even a simple windows application!
                    >
                    On the other hand a simple and complete WinForms application is also
                    feasible in only a few lines of code. For example:
                    >
                    using System;
                    using System.Drawing;
                    using System.Windows. Forms;
                    >
                    class Test
                    {
                    [STAThread]
                    static void Main()
                    {
                    Form form = new Form {
                    Controls = { new Button {Name="Button", Text="Click me"}},
                    Size = new Size(500, 500)
                    };
                    form.Controls["Button"].Click += delegate
                    { MessageBox.Show ("Hello"); };
                    Application.Run (form);
                    }
                    >
                    OK, when I get to that level of sophistication, maybe I won't need you
                    then.
                    }
                    {
                    Form2 frm2 = new Form2(myClass1, mYClass2); //<--do you
                    know, reading this thread, why we are using parametric constructors
                    rather than default parameterless constructors?
                    >
                    Yes, you're using it to pass information to Form2. As we've already
                    discussed, there are other ways of doing that.
                    >
                    True enough, though in my mind other than the example of inheriting a
                    form, and using a method from a class that's nested in the base class,
                    I really don't see how. Far more flexible to pass objects--oops, I
                    meant variables--to the second or derived form. I mentioned in
                    passing that you can maybe use delegates/events between forms, but the
                    more I think about it, the more I see that getting the events
                    recognized might be a problem. Maybe you can insert "delegate <type>
                    VariableName (type)" throughout both forms, and maybe that will work,
                    but without seeing an example I'm not about to waste an hour or two
                    trying to find out. Besides there's a hoary tradition in C++ of using
                    the constructor to pass all kinds of information--I'm sure you've seen
                    the 'modern' constructor format of C++ (which C# sadly does not have)
                    where you can, after the colon, do stuff like INTergerI(jay),
                    BooL(true)... etc, which is equal to INergerI = jay; BooL = true;
                    inside the bracket { } . If you're not familiar with C++ forget all
                    of this. In short, I like using the constructor to pass objects and
                    until I see a concrete example (other than the derived classes/ nested
                    classes example discussed) I'm sticking to that convention, since it
                    works. If it ain't broke, don't fix it.

                    >
                    >
                    frm2.Show();
                    }
                    ////////// END OF PARTIAL CLASS FORM1 : Form
                    >
                    // start of Partial Class Form 2: Form
                    namespace MDIForms
                    {
                    public partial class Form2 : Form
                    {
                    Class2 myClass2;
                    Class1 myNewClass1;
                    public Form2() //default constructor not used
                    {
                    InitializeCompo nent();
                    myClass2 = new Class2();
                    myNewClass1 = new Class1(99, "new!Class1!!") ;
                    }
                    public Form2(Class1 passClass1, Class2 passClass2)
                    {
                    >
                    Interesting that you're not calling InitializeCompo nent() (or
                    explicitly calling "this()" as a constructor initializer). Of course,
                    you haven't shown what Form2 actually does, but you'll find that if you
                    put some controls on it in the designer, those *won't* be seen when the
                    form is displayed by Form1.clikMeNew FToolStripMenuI tem_Click.
                    I did add InitializeCompo nent() in the parametric form, but I
                    accidentally deleted it when I posted the (incomplete) code in my
                    haste to make it more readable. Sorry.
                    >
                    myClass2 = passClass2;
                    myNewClass1 = passClass1;
                    }
                    // end of Partial Class Form 2: Form
                    >
                    Discussion: classes 1,2 are simple classes, that contain a public
                    int
                    and public string as members, declared OUTSIDE the Form1 class, and
                    are not nested to the Form1 class, nor is Form 2 inherited from
                    Form1, but the important point is that in C# there is 'hiding' of
                    previously declared classes.
                    >
                    Nope, the classes aren't hidden at all. To prove it, just write:
                    >
                    new Class1(0, "");
                    new Class2();
                    >
                    in the constructor. Obviously it won't do a lot of good (unless those
                    constructors do interesting things) but the fact that it compiles
                    proves that the classes aren't hidden.
                    OK, thanks for that terminology. Hiding is not the best word, perhaps
                    'local variable overriding of outer scope (?) variables of the same
                    name'. Or something like that. OK I got it. Or maybe not. Moving
                    right along...
                    >
                    You *could* effectively hide them (so they'd need to be referenced in a
                    more explicit way, e.g. with the "global" namespace alias) by genuinely
                    declaring Class1 and Class2 inside Form1, e.g.
                    >
                    public partial class Form1 : Form
                    {
                    class Class1 {}
                    class Class2 {}
                    >
                    Class1 myClass1; //cannot comment out this line--compile error
                    Class2 mYClass2;
                    >
                    // Code as before
                    >
                    At that point variables myClass1 and mYClass2 would refer to the nested
                    classes; the constructor call to Class1 within the Form1 constructor
                    wouldn't compile as the appropriate constructor signature hasn't been
                    declared, and clikMeNewFToolS tripMenuItem_Cl ick wouldn't compile
                    because the types of the Form2 constructor call would be incompatible.
                    >
                    Interesting, thanks. You left out an important detail--when there is
                    ambiguity, how can you tell the compiler to 'override' the ambiguity
                    and compile? In C# there is no easy way, for example, if the Class1
                    and Class2 variables are in namespace XYZABC, you can maybe write
                    XYZABC.Class1 myClass1; etc., but everytime I tried this it doesn't
                    compile (Update: I see the 'this' pointer below solves some
                    ambiguity)
                    This is illustrated by the line //
                    Class1 myClass1 = new Class1(100, "heLlO1YouTube! "); //HIDES or
                    'overrides' previous declaration!
                    >
                    That's not hiding a class. That's hiding an instance variable with a
                    local variable.
                    OK, terminology noted, thanks.
                    >
                    {Jon would argue this is imprecise terminology: it's "declaring a
                    variable called myClass0, of *type* Class0.", and would then point out
                    that "hiding" is an imprecise word to use, since you are declaring and
                    defining and instantiating a new local variable that has the same name
                    as the variable "myClass0".
                    >
                    Hiding is a perfectly fine word to use - but saying you're declaring a
                    class when you're actually declaring a variable is hugely misleading.
                    OK, noted. If this is in your book I'll study it, but likely if not
                    I'll forget it five minutes after I post this thread.
                    >
                    Feel free. If you see me make a mistake, I'll welcome the correction.
                    Every computer science book--and even the good ones--have errors, so I
                    appreciate your modesty.
                    >
                    Even though myClass1 is declared outside the default constructor of
                    Form1, it is 'overridden' (I am using imprecise terminology, but if
                    you're astute you will understand the problem) by the second
                    declaration of myClass1 inside the default constructor of Form 1.
                    >
                    Indeed. Although you could still access it as "this.myClass1" . If you
                    change this line:
                    myClass1 = new Class1(100, "heLlO1YouTube! ");
                    to
                    this.myClass1 = new Class1(100, "heLlO1YouTube! ");
                    >
                    in the Form1 constructor and uncomment this line:
                    Class1 myClass1 = new Class1(100, "heLlO1YouTube! ");
                    >
                    then the program will work without a NullReferenceEx ception.
                    Wow! You're good. I played around and see what you're talking about,
                    even though I'm not 100% clear on why the 'this' pointer (the object
                    calling 'Form1()') makes such a difference, but maybe the object/
                    variable understand to use the 'outermost' Class1. Leaving out the
                    'this' pointer did give a nice compiler warning CS0136, which, had I
                    seen it before, would have obviated having to write this entire thread
                    (though I guess I would not have learned as much).

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

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

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

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

                    // end of playing

                    >
                    And, using this 'wrong' way, you will get a null reference passed to
                    Form2, which is not correct.
                    And, commenting out the line "Class1 myClass1; //cannot comment out
                    this line--compile error" is even worse--you will get a compile error
                    rather than a runtime error, since myClass1 inside the normal default
                    constructor of Form1 will be treated as a local variable that cannot
                    be seen elsewhere.
                    >
                    Indeed, although I'd argue that a compile-time error is *better* rather
                    than an execution time error. If we wanted to leave all errors until
                    execution time, we'd use a dynamic language...
                    OK.
                    >
                    If you understand this simple example you're half way towards
                    understanding the problem in this thread. {assuming you even care
                    about understanding the problem rather than pushing your own agenda}
                    >
                    Your simple example doesn't show anything that couldn't be more easily
                    shown in a complete console app.
                    Assuming I knew what the problem was.

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

                    RL

                    Comment

                    • Jon Skeet [C# MVP]

                      #11
                      Re: How to pass information, classes between forms in WindowsApplicat ion mode [ FINALLY!]

                      On Jul 23, 11:40 pm, raylopez99 <raylope...@yah oo.comwrote:
                      raylopez99 <raylope...@yah oo.comwrote:
                      In that case I guess it's the end of the discussion.
                      >
                      I did learn a few things in this exchange, which I'll summarize
                      below. Thanks for replying.
                      I'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 InitializeCompo nent, 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.WriteLi ne 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.ReadLin e() 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=somet hing;) and gives the intended result, unlike my
                      commented out code.
                      Yup. Using "this.myCla ss1" 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 clikMeNewFToolS tripMenuItem_Cl ick wouldn't compile
                      because the types of the Form2 constructor call would be incompatible.
                      >
                      Interesting, thanks.  You left out an important detail--when there is
                      ambiguity, how can you tell the compiler to 'override' the ambiguity
                      and compile?  In C# there is no easy way, for example, if the Class1
                      and Class2 variables are in namespace XYZABC, you can maybe write
                      XYZABC.Class1 myClass1; etc., but everytime I tried this it doesn't
                      compile  (Update:  I see the 'this' pointer below solves some
                      ambiguity)
                      "this" 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::Namespa ce.Goes.Here.Cl assname

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

                      Comment

                      • Jon Skeet [C# MVP]

                        #12
                        Re: How to pass information, classes between forms in WindowsApplicat ion mode [ FINALLY!]

                        On Jul 24, 1:58 pm, raylopez99 <raylope...@yah oo.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:


                        Jon

                        Comment

                        • Jon Skeet [C# MVP]

                          #13
                          Re: How to pass information, classes between forms in WindowsApplicat ion mode [ FINALLY!]

                          On Jul 25, 11:50 am, raylopez99 <raylope...@yah oo.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

                          Comment

                          Working...