[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 236
  • Last Modified:

Scope of Variables in Windows Forms

Could someone tell me if there is an exception to variable scope with Windows forms?  The way I understand it, is that a form is just another class.  So in theory, if a variable is defined as private in a windows form it should not be accessible to other objects in the code and vice versa correct?  I'm asking this question because I am having the following problem which I am not understanding:

I am building an add-in for word.  In the main class, Connect, I declare a private arraylist variable named "x".  I also have a form which contains an arraylist variable declared as private which is also named "x".  For some reason, if I add and object to the arraylist within the form code, it makes its way into the private arraylist defined in the calling class.  Does anyone know why this would happen?  I am showing the form as a dialog box if that makes a difference.

Thanks in advance for your help!
0
kaedo
Asked:
kaedo
  • 5
  • 2
  • 2
1 Solution
 
EagleEye1975Commented:
The best way to be sure your variable is going to the right place is to completely write out the variable's name, including the desired scope.

For example:

Public Class MyClass
   Private X as new String
   Dim NewClass as new NewClass
End Class

Public Class NewClass
  Private X as new String
End Class

MyClass.X = "One string"
MyClass.NewClass.X = "A different string"

See what I'm talking about?

The scope would also depend on inheritance I believe.  If a subclass inherits from another, duplicate declaraions could get confused.

Of course, the other way to get around this problem is to properly name your variables so the confusion doesn't have a chance to occur. :)  Generally speaking, using the same name for variables in different scopes is bad coding. :)
0
 
kaedoAuthor Commented:
Thanks for your help.  I tried your suggestions of renaming the variables and qualifying the names but I am still getting the same result.  I believe it has to do with the fact that I am setting the form variable based on the original variable in the class via a property on the form.  So in short, here's basically what I have:

Public Class MyClass
  Private _myClassList As New ArrayList

  Public Sub LaunchForm()
    Dim myFormClass As New MyFormClass
    myFormClass.MyFormList = myClassList
    myFormClass.ShowDialog()
  End Sub
End Class

Public Class MyFormClass
  Private _myFormList As New ArrayList
    Public Property MyFormList() As ArrayList
        Get
            Return Nothing
        End Get
        Set(ByVal Value As ArrayList)
            _myFormList = Value
        End Set
    End Property
  Public Sub MyFormClass_Load()
    _myFormList.Add(New Object)
  End Sub
End Class

What I'm trying to do is pass the original arraylist to the form so that the form can do whatever it wants with it.  But I don't want it to update the arraylist in the calling class.  Maybe I don't understand completely how properties work but I thought that if you passed a variable using the ByVal keyword, the underlying variable could not be changed.  So I would think this would work but it doesn't.  Instead, when the form adds a new object to its own private array list (regardless of the name of the variable), it adds the object to the arraylist variable that was originally passed to the form.

Any thoughts?  Thanks again for your help!
0
 
EagleEye1975Commented:
Where are your "Sub New" areas?

When you declare a NEW instance of a class, the "sub new" portion of the class is run to instantiate the values in the class...
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
kaedoAuthor Commented:
Here's the entire set of code in case this will help more:

'Start code****************************************************
Imports Microsoft.Office.Core
Imports Extensibility
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Core.MsoControlType
Imports Microsoft.Office.Core.MsoButtonStyle

<GuidAttribute("75A30EBA-3B8E-4999-83EF-2EA8860B0CB9"), ProgIdAttribute("KARECLetter.Connect")> _
Public Class Connect

    Implements Extensibility.IDTExtensibility2

    Private _myClassList As New ArrayList

    Private Sub LaunchForm()

        Dim myFormClass As New MyFormClass
        Dim myObject As Object

        'Add one object to the object array list
        _myClassList.Add(New Object)

        myFormClass.MyFormList = _myClassList

        myFormClass.ShowDialog()

        'Loop through objects
        For Each myObject In _myClassList
            MsgBox("Here's an object")
        Next

    End Sub

End Class

Public Class MyFormClass
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        '
        'MyFormClass
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Name = "MyFormClass"
        Me.Text = "MyFormClass"

    End Sub

#End Region

    Private _myFormList As New ArrayList

    Public Property MyFormList() As ArrayList
        Get
            Return Nothing
        End Get
        Set(ByVal Value As ArrayList)
            _myFormList = Value
        End Set
    End Property
    Private Sub MyFormClass_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        _myFormList.Add(New Object)

    End Sub

End Class
'End Code**********************************************************************

Any thoughts?
0
 
Arthur_WoodCommented:
this code:

        Dim myFormClass As New MyFormClass
        Dim myObject As Object

        'Add one object to the object array list
        _myClassList.Add(New Object)

        myFormClass.MyFormList = _myClassList

        myFormClass.ShowDialog()

is passing a REFERENCE to the _myCLassList object, to the MyFormClass.  But that means that any changes made to the CONTENTS of the _myClassList object made in MyFormClass will be reflected in the _myClassList in the Connect class.  Is that what you are troubled by?

AW
0
 
kaedoAuthor Commented:
Yes, that is what is troubling me.  I don't understand why it is passing a reference to the object, especially when the SET statement of the MyFormList property specifies the argument as ByVal.  How would this typically be accomplished (i.e. when you need to pass an array list to another form but not impact the original array)?  Thanks for your comments!
0
 
Arthur_WoodCommented:
passing an OBJECT by value does not do what you seem to think it does.  The object REFERENCE still provides 'access' to the contents of the object - so that the 'value' of the object can be modified.  if you do not want the contents to be modified, then you should make a local 'copy' of the contents.

AW
0
 
kaedoAuthor Commented:
Thanks for your help; I didn't realize it worked like this.  Can you give me an example of how I would make a local 'copy' the contents?
-K
0
 
kaedoAuthor Commented:
I found this article which describes "shallow" copying versus "deep" copying.

http://www.csharpfriends.com/quickstart/howto/doc/clone.aspx

Thanks for pointing me in the right direction Arthur.  By default, when an arraylist is copied or cloned, it uses shallow copying which consists of references to the orginal objects, not actual "copies" of the objects.  That was my problem.  The article above describes a method for deep copying an arraylist.

Thanks again for the help!
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

  • 5
  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now