Solved

Passing generic lists by val

Posted on 2011-02-14
6
565 Views
Last Modified: 2012-05-11
Is there a way to pass a generic list (List of T) by val instead of By Ref?

I created a test app that had this:

Public Class Vendor
   private m_Id as integer
   public property ID as integer
      Get
            Return (m_id)
        End Get
        Set(ByVal value As integer)
            m_id= value
        End Set
    End Property
end Class



No I created another class

Public class Test
  private mList as new list(of Vendor)

  public sub New(VendorList as list(of Vendor))
      mList = VendorList
      mList.Clear()
  end sub
end class


No in main form I click a button and do this:

Dim myList As New List(Of Vendor)
        For i As Integer = 0 To 10
            Dim v As New Vendor
            v.Id= i
            myList.Add(v)
        Next

        Dim t As New Test(myList)
        MsgBox("List Count: " & CStr(myList.Count))



The results show that the clear function in the Test class cleared the passed in list even though it was passed by val.   Back in form1 the msgbox shows the count as 0.

Is there a way I can pass the list to Test without it actually clearing the original list?

0
Comment
Question by:rutledgj
6 Comments
 
LVL 23

Expert Comment

by:wdosanjos
ID: 34889330
I think you just need to remove the .Clear from the Test class as follows:

Public class Test
  private mList as new list(of Vendor)

  public sub New(VendorList as list(of Vendor))
      mList = VendorList
  end sub
end class

Open in new window

0
 
LVL 23

Accepted Solution

by:
wdosanjos earned 500 total points
ID: 34889361
BTW, Lists are always passed by ref.  If you need just a copy, you need to create a copy explicitly.  For example:

Public class Test
  private mList as new list(of Vendor)

  public sub New(VendorList as list(of Vendor))
      mList = new List(of Vendor)(VendorList)
  end sub
end class

Open in new window

0
 

Author Comment

by:rutledgj
ID: 34889362
I know that will fix it. The whole point of this was to test if clearing it in the class would affect the original list.  I need a way to pass the original list in so that whatever I do to the list in the Test class does not affect the original list in form1.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 23

Expert Comment

by:wdosanjos
ID: 34889494
Lists are always passed by Ref. You need to explicitly create a copy as follows:

Public class Test
  private mList as new list(of Vendor)

  public sub New(VendorList as list(of Vendor))
      mList = new List(of Vendor)(VendorList)
      mList.Clear()
  end sub
end class

Open in new window

0
 
LVL 85

Expert Comment

by:Mike Tomlinson
ID: 34889573
" I need a way to pass the original list in so that whatever I do to the list in the Test class does not affect the original list in form1"

wdosanjos already gave you the correct answer:

    "you need to create a copy explicitly"

What you do intend to do with List in your Test Class?...
0
 

Expert Comment

by:khufford19
ID: 34993822
I have a related question that I'm having some trouble with.  I have a custom object (created as a structure).  For example purposes, I'll call my object ItemDetails here.  In the course of my application, I do a check to see if the object I'm trying to update already exists in my database.

            Dim UpdatedItem As ItemDetails
            Dim ExistingItems As New List(Of ItemDetails)

            For Each DatabaseRow As DataRow In DatabaseTable.Rows
                UpdatedItem = New ItemDetails

                UpdatedItem = GetItemFromDatabase(DatabaseRow)

                ExistingItems = GetExistingItemDetail(UpdatedItem)

                If Not IsNothing(ExistingItems) Then
                    For I As Integer = 0 To ExistingItems.Count
                        UpdateItemData(UpdatedItem, ExistingItems(I))
                    Next
                Else
                    InsertNewRecord(UpdatedItem)
                End If

                UpdatedItem = Nothing

                Application.DoEvents()
            Next DatabaseRow

Open in new window


To check this, I call a function that is supposed to return a list of my ItemDetails object (GetExistingItemDetail).  When I don't find a matching record, the function is written to return a value of Nothing.  These calls to the function work exactly as expected.

However, when I actually find a duplicate record in the database, the function won't return a valid List(Of ItemDetails).

    Private Function GetExistingItemDetail(ByVal UpdatedItem As ItemDetails) As List(Of ItemDetails)
        Dim FoundItems As New List(Of ItemDetails)
        Dim DatabaseItems As New DataTable
        Dim ExistingAdapter As New OleDb.OleDbDataAdapter

        SQLStr = "SELECT * FROM Items " _
                & "WHERE ItemID = '" & UpdatedItem.ID & "'"

        Try
            ExistingAdapter = New OleDb.OleDbDataAdapter(SQLStr, GAPConn)

            DBConn.Open()
            ExistingAdapter.Fill(DatabaseItems)
        Catch DBException As Exception
            MsgBox("There was a problem retrieving the data for item " & UpdatedItem.ID & vbCrLf _
                   & DBException.Message, MsgBoxStyle.Critical + MsgBoxStyle.OkOnly, "DATABASE ERROR")

            FoundItems = Nothing
        Finally
            ExistingAdapter = Nothing
            DBConn.Close()
        End Try

        ' *********************************************************************
        ' ** If a database error occurred above, return nothing and exit the **
        ' ** function to prevent further execution in this function.         **
        ' *********************************************************************
        If IsNothing(DatabaseItems) Then
            FoundItems = Nothing

            Return FoundItems
            Exit Function
        End If

        ' *********************************************************************
        ' ** If no loans were found, return nothing and exit the function.   **
        ' *********************************************************************
        If DatabaseItems.Rows.Count = 0 Then
            FoundItems = Nothing
            DatabaseItems = Nothing

            Return FoundItems
            Exit Function
        End If

        Try
            For I As Long = 0 To DatabaseItems.Rows.Count - 1
                Dim Item As New ItemDetails
                Dim CurrentItem As DataRow

                CurrentItem = DatabaseItems.Rows(I)

                ' *********************************************************************
                ' **Here's where the Item object is populated.
                ' *********************************************************************

                I = I + 1

                ' *********************************************************************
                ' ** Add the waiver we just populated to the array list, reset the   **
                ' ** temporary waiver object and check for the next record.          **
                ' *********************************************************************
                FoundItems.Add(Item)
                Item = Nothing
                CurrentItem = Nothing
            Next I
        Catch DBException As OleDb.OleDbException
            MsgBox("An error occurred retrieving the data for item " & UpdatedItem.ID)
        End Try

        Return FoundItems
    End Function

Open in new window


If I check the FoundItems object when it actually makes it all the way to the end of the function, I see that it actually contains an item.  But, when I get back to the calling function, the List(Of ItemDetails) that I tried to return appears to be invalid.  Is there something that I'm missing/overlooking here?
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create and use a custom WaterMark textbox class.  The custom WaterMark textbox class allows you to set the WaterMark Background Color and WaterMark text at design time.   IMAGE OF WATERMARKS STEPS Create VB …
This tutorial demonstrates one way to create an application that runs without any Forms but still has a GUI presence via an Icon in the System Tray. The magic lies in Inheriting from the ApplicationContext Class and passing that to Application.Ru…
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
Both in life and business – not all partnerships are created equal. As the demand for cloud services increases, so do the number of self-proclaimed cloud partners. Asking the right questions up front in the partnership, will enable both parties …

911 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

23 Experts available now in Live!

Get 1:1 Help Now