webForumDet fria alternativet

Problem med List(Of T) och referens

.NET

5 svar · 697 visningar · startad av Webslave

Medlem sedan maj 2002647 inlägg
Frågan#1

Jag har en funktion som gör lite kontroller om det finns ett object med samma datum som det jag söker efter och isf. ska den utföra lite åtgärder. Funktionen ser ut såhär:

Public Function CheckWeekRestSchedule(ByVal addedCycles As List(Of CCycle), ByVal schedule As CSchedule) As Boolean

        Dim r_value As Boolean = True
        Dim today, tomorrow, lastUsed As New CCycle
        Dim i, y As Integer
        Dim daysPassed As Integer
        Dim newCycle As CCycle
        Dim firstCycle As New CCycle
        Dim newDate As Date
        Dim x As Integer = 0
        Dim cycles As New List(Of CCycle)

        cycles = addedCycles

        ' I denna så börjar det att strula
        Do Until x = schedule.ScheduleWeekBreak
            newCycle = New CCycle
            newDate = Format(DateAdd(DateInterval.Day, (7 * schedule.ScheduleCycles) + x, Now), "Short Date")
            newCycle = New CCycleFinder(cycles, Format(DateAdd(DateInterval.Day, x, Now), "Short Date")).Found
            newCycle.CycleDate = newDate
            cycles.RemoveAt(New CCycleIndexFinder(cycles, newCycle.CycleDate).Found)
            cycles.Add(newCycle)
            x = x + 1
        Loop

        cycles.Sort(AddressOf CCycle.CompKeysByName)

        ' Massa kod som inte har med frågan att göra

        Return r_value

    End Function

Problemet är att den listan med ccycles som jag skickar med här (addedCycles) modifieras även den och det vill jag inte utan jag vill endast att det ska vara i just denna funktion som den aktuella listan (cycles) justeras. Jag kör inte med ByRef så jag har lite svårt att förstå varför det blir fel. Om jag lägger till denna funktion före stället så fungerar det bra men det ser ju hemskt ut.

For Each c As CCycle In addedCycles
            newCycle = New CCycle
            newCycle.CycleDate = c.CycleDate
            newCycle.CycleStartTime = c.CycleStartTime
            newCycle.CycleEndTime = c.CycleEndTime
            newCycle.CycleBreak1Start = c.CycleBreak1Start
            newCycle.CycleBreak1End = c.CycleBreak1End
            newCycle.CycleBreak2Start = c.CycleBreak2Start
            newCycle.CycleBreak2End = c.CycleBreak2End
            newCycle.CycleBreak3Start = c.CycleBreak3Start
            newCycle.CycleBreak3End = c.CycleBreak3End
            newCycle.CycleCycle = c.CycleCycle
            newCycle.CycleDay = c.CycleDay
            cycles.Add(newCycle)
        Next

Ser någon vad det är jag missar? Jag har antagligen snubblat över någon superenkel programmeringslogik men är man helt självlärd så missar man en hel del grundläggande saker ;)

Medlem sedan juni 20008 205 inlägg
#2

När du säger cycles = addedCycles pekar på båda referenserna på samma objekt. Det du vill göra är att göra en cycles till en ny lista med samma innehåll som addedCycles, List har en konstruktor som tar emot en IEnumerable som är lämplig för att kopiera andra listor. (Ändrar du på CCycle-elementen i listan får du göra den kopieringen du visar. En bättre idé vore kanske dock att fixa din kod så att du inte ändrar på objekten...)

Medlem sedan maj 2002647 inlägg
#3

Tack för fingervisningen, fick mig att kunna leta på rätt ämnen och hittade denna lösning, fungerar (än så länge) klockrent!

Imports System.Reflection
Public Class CCloneableList(Of T)
    Inherits List(Of T)
    Implements System.ICloneable
    Function Clone() As Object Implements System.ICloneable.Clone
        Dim NewList As New CCloneableList(Of T)
        If Me.Count > 0 Then
            Dim ICloneType As Type = Me(0).GetType.GetInterface("ICloneable", True)
            If Not (ICloneType Is Nothing) Then
                For Each Value As T In Me
                    NewList.Add(CType(Value, ICloneable).Clone)
                Next
            Else
                Dim MethodsList() As MethodInfo = Me(0).GetType.GetMethods
                For Each Value As T In Me
                    NewList.Add(Value)
                Next
            End If
            Return NewList
        Else
            Return NewList
        End If
    End Function
End Class

Här hittade jag klassen och det finns lite andra bra-och-ha-koder här så jag tänkte dela med mig! http://programmingcorner.blogspot.com/2007/01/deep-cloning-in-net.html

Medlem sedan juni 20008 205 inlägg
#4

Argh. Inte världens bästa kod, kanske. Frågor:

  • Vad händer med MethodsList?
  • Vad händer om man har en lista som innehåller objekt av olika klasser, varav vissa implementerar ICloneable, andra inte?

Det är dessutom ett ganska överdrivet sätt att kopiera en lista på. Vill man verkligen göra en deep clone (vilket jag verkligen undrar - ändrar du verkligen på CCycle-objekten?) skulle följande räcka (C#):

var cycles = new List<CCycle>(from c in addedCycles select (CCycle)c.Clone());

Nu blir iofs inte cycles klonbar, men det behöver du inte, och det är mycket bättre design att inte kräva att parametern som skickas in är av en obskyr subklass till List<T> - det är en implementationsdetalj att du behöver kopiera listan. I framtiden kanske du kan fixa din algoritm så att du inte behöver kopiera allt.

Medlem sedan maj 2002647 inlägg
#5

Jag såg kanske inte till hur bra koden är (det känns som att jag inte är den att dömma hehe) utan mer till att den gjorde det jag ville :)

Alla nya idéer är värda att prövas så vi gör ett försök med din :)

Jag försöker skriva om din kodsnutt till .Net men får ett problem vid "(from c in addedCycles)" där "from" inte accepteras... någon idé?

Medlem sedan juni 20008 205 inlägg
#6

Det är LINQ, har inte riktigt koll på hur det ser ut i VB men http://www.google.com/search?q=visual basic linq&hl=en ger http://msdn.microsoft.com/en-us/library/bb384508.aspx

261 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
126 ms — deklarationer (db)
0 ms — hämta statistik (cache)
133 ms — hämta tråd, inlägg och bilagor (db)
126 ms — ändringar (db)