rutledgj
asked on
Passing generic lists by val
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?
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?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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.
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
" 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?...
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?...
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.
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).
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?
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
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
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?
Open in new window