Search code examples
vb.netlistclassclonedeep-copy

Deep copying of elements in a List (Of Class)


Good evening.

I'm trying to do a deep copy of some of the elements of a list, and I'm finding it extremely hard to do. There's a lot of new concepts I'm trying so bear with me if some of the following code seems weird...

I have the following lists:

accountList as List(Of Account)
accountsInArea as New List(Of Account)
result as New List(Of Account)

Where each element's type is a Class defined by myself:

Public Class Account

Enum AddingType
    income
    expenditure
End Enum
Enum AreaType
    high
    mid
    low
End Enum

Property Area() As AreaType
Property Group() As String
Property AccountNumber() As Integer
Property AccountDescription() As String
Property IncomeExpenditure() As AddingType
Public Property MonthlyValues As New Dictionary(Of Integer, Decimal)
End Class

I need to find certain items of accountList and copy the values to a new list: accountsInArea. For now, I have used the following method:

accountsInArea = accountList.FindAll(Function(acc) acc.Area = area)

However, this produces a copy of the reference to those items the Lambda Expression produces (doesn't it?). If I understood correctly while surfing around SO and MSDN, what I need is a deep copy of the elements.

I'd like accountsInArea to have a copy of all the items .FindAll produced, including (especially) those in the MonthlyValuesDictionary.

I have tried:

accountsInArea = accountList.Select(accountList.FindAll(Function(acc) acc.Area = area))

Also:

For Each account In accountList.FindAll(Function(acc) acc.Area = area)
    accountsInArea.Add(account)
Next

And lastly adding to the Class:

Implements ICloneable

Public Function Clone() As Object Implements System.ICloneable.Clone
    Return Me.MemberwiseClone
End Function

And using inside the method:

accountsInArea = accountList.FindAll(Function(acc) acc.Area = area)
    result = accountsInArea.Select(Function(acc) acc.Clone()).Cast(Of Account).ToList

Help would be GREATLY appreciated.


Solution

  • just implement ICloneable in your Class, and

    Dim accountsInArea As List(Of Account) = accountList.Where(Function(x) x.Area = Account.AreaType.high).Select(Function(y) y.clone).Cast(Of Account)().ToList
    

    here full code in your ex

    Sub AccountListProg
        Dim accountList As New List(Of Account) From {New Account With {.Area = Account.AreaType.high, .AccountNumber = 1}, _
                                                       New Account With {.Area = Account.AreaType.high, .AccountNumber = 2}, _
                                                       New Account With {.Area = Account.AreaType.low, .AccountNumber = 3}, _
                                                       New Account With {.Area = Account.AreaType.mid, .AccountNumber = 4}}
    
        Dim accountsInArea As List(Of Account) = accountList.Where(Function(x) x.Area = Account.AreaType.high).Select(Function(y) y.clone).Cast(Of Account)().ToList
    End Sub
    
    Public Class Account
        Implements ICloneable
        Public Function Clone() As Object Implements ICloneable.Clone
            Return New Account With {.AccountDescription = AccountDescription, _
                                 .AccountNumber = AccountNumber, _
                                 .Area = Area, _
                                 .Group = Group, _
                                 .IncomeExpenditure = AddingType.income, _
                                 .MonthlyValues = MonthlyValues}
        End Function
        Enum AddingType
            income
            expenditure
        End Enum
        Enum AreaType
            high
            mid
            low
        End Enum
    
        Property Area() As AreaType
        Property Group() As String
        Property AccountNumber() As Integer
        Property AccountDescription() As String
        Property IncomeExpenditure() As AddingType
        Public Property MonthlyValues As New Dictionary(Of Integer, Decimal)
    End Class