Solved

Passing generic lists by val

Posted on 2011-02-14
6
561 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
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 
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

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Article by: jpaulino
XML Literals are a great way to handle XML files and the community doesn’t use it as much as it should.  An XML Literal is like a String (http://msdn.microsoft.com/en-us/library/system.string.aspx) Literal, only instead of starting and ending with w…
I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

708 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

12 Experts available now in Live!

Get 1:1 Help Now