När du skapar en metod i VB.Net blir parametrar ByVal om du inte anger någonting annat. Detta innebär att du vill få en lokal kopia av ditt objekt in till din metod. Det man ofta inte tänker på är att man inte får en kopia av eventuella underliggande objekt. Om inte dina objekt har en impelentation som automatisk hanterar det som kallas ’Deep cloning’.

Det som händer vid ett metodanrop med en ByVal-parameter är att en ’Shallow cloning’ görs. Detta innebär att ditt objekt kopieras, men eventuella underliggande objekt som det objektet pekar på kopieras inte, och alltså pekar på samma objekt. Vi kan exemplifiera detta med en Collection av typen Arraylist där varje element i listan innehåller ett objekt av typen MinKlass.

Klassen MinKlass består av två properties, ID och Namn. I Arraylist minLista har vi lagt två element, ett med namnet ”Stig” och ett med namnet ”Helmer”. ID skapas av klassen själv vid initiering.

Sedan skickas minLista in till en metod (sub)

private sub Check(ByVal ArrayList lista)

I metoden Check görs följande:

 

For Each min As MinKlass In lista
     min.Namn = ”Arne”
Next

Vad som man vill skall hända här är att den lokala listan lista’s objekt av typen MinKlass skall ändras. Det som händer är att när du anropar metoden ‘Check’ görs en ‘shallow clone’ på objektet minLista till lista, vilket innebär att endast själva objektet minLista kopieras till lista. De underliggade objekten MinKlass1 och MinKlass2 kopieras inte, utan lista pekar fortfarande på MinKlass1 och MinKlass2:

 

Har man jobbat med exempelvis C++ tidigare och man vet att de flesta objekt i .Net är referenstyper kan detta te sig självklart. Där är man van vid att hantera pekare och ‘adresserade’ objekt.

Orsaken till detta är att det som lagras i minLista endast är en pekare till objekten MinKlass1 och MinKlass2.

Även om man i funktionen Check gör en (tror man) lokal kopia på varje objekt (MinKlass1 och MinKlass2), är det också då själva adressen som pekar på objekten man gör en kopia på. För att man skall kunna göra en ‘Deep Clone’ måste man implementera stöd för det i sin klass, eller kopiera objekten property för property.

Så för att man skall kunna använda lokala kopier på MinKlass-objekten måste man alltså själv se till att det finns lokala kopier på objekten. Har du serialiserbara objekt kan du använda serialisering för att skapa en kopia och då ha en generell funktion som kan hantera kopiering av olika typer av objekt. Annars kan man applicera interfacet ICloneable på sin klass eller skapa copy-constructors.

Olika sätt att göra på finns exempelvis beskrivet på http://www.windojitsu.com/blog/copyctorvsicloneable.html.

Man kan även se att Brad Adams diskuterar om man skall använda ICloneable överhuvudtaget.

Annonser