Jag har stött på något frustrerande som jag skulle vilja ha förklarat för mig :) Nedan har jag skrivit ett enkelt exempel på det som är frustrerande.
Jag försöker lägga till en ny kolumn i en datatabell men det verkar inte finnas någon skillnad mellan att använda sig av byval och byref. Om jag vill att nedanstående kod ska fungera måste jag använda byval samt kopiera tabellen. Det känns lite kaka på kaka. Någon som kan förklara varför man måste göra så?
Det jag vill är alltså att bara tblDataNew får en ny kolumn men inte att tblData får det.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim tblData As New DataTable
Dim tblDataNew As DataTable
tblData.Columns.Add(New DataColumn("Column1"))
tblDataNew = AddColumnByVal(tblData, "Test1")
'Result: Både tblData och tblDataNew har fått en ny kolumn
tblDataNew = AddColumnByRef(tblData, "Test2")
'Result: Både tblData och tblDataNew har fått en ny kolumn (fungerar på samma sätt som anropat ovan)
tblDataNew = AddColumnByVal(tblData.Copy, "Test3")
'Önskvärt result: tblDataNew har fått en ny kolumn
End Sub
Private Function AddColumnByVal(ByVal tblData As DataTable, ByVal columnName As String) As DataTable
tblData.Columns.Add(New DataColumn(columnName))
Return tblData
End Function
Private Function AddColumnByRef(ByRef tblData As DataTable, ByVal columnName As String) As DataTable
tblData.Columns.Add(New DataColumn(columnName))
Return tblData
End Function
En datatable liksom andra objekt som kund-, orderobjekt m.m. är referensobjekt. Detta var lite nytt för mig. Jag hittade en sida som beskrev detta med referensobjekt:
"It is important to know that reference types are always passed by reference. "By Reference" is when an argument is passed to a function by passing a reference to the actual value. In this case, if you change the argument in the function, you also change the original.
If you specify that a reference type should be passed by value, a copy of the reference is made and the reference to the copy is passed *."
Källa: http://petesbloggerama.blogspot.com/2006/01/value-types-reference-types-and.html
Jag tycker ändå att det är väldigt konstigt. Jag förstår inte varför Microsoft har skapat det så här. För det innebär att det inte är egentligen någon större skillnad på byval och byref. Men rekommendation borde vara att alltid använda sig av byref när det kommer till referensobjekt. För varför skulle man vilja skapa en kopia av referensen med hjälp av byval? Någon som kan förklara vad Microsoft har tänkt sig att syftet med detta är?
spangoMedlem sedan juni 20008 205 inlägg
Lukaspojken skrev:
Någon som kan förklara vad Microsoft har tänkt sig att syftet med detta är?
För att det ska funka på samma sätt som i alla andra språk som finns i hela världen? ;)
Lukaspojken skrev:
Men rekommendation borde vara att alltid använda sig av byref när det kommer till referensobjekt. För varför skulle man vilja skapa en kopia av referensen med hjälp av byval?
Finns egentligen ingen anledning att inte göra det. Skillnaden mellan ett byval- och ett byref-anrop är att byref bara skickar in en pekare till värdet på den variabel man använder sig av, och sen avrefereras den pekaren automatiskt i när man använder parametern i funktionen.
Alla variabler av referenstyp är egentligen pekare, så när man använder byref på en referenstyp får man en pekare till en pekare. Detta innebär inte bara dubbelarbete när man avrefererar, utan också att man kan ändra på vilket objekt den inskickade variabeln pekar på. Om du inte har väldigt goda skäl att använda byref - låt bli. Det finns språk som inte ens har någon funktionalitet som byref (Java är ett exempel), och det går i de flesta fall alldeles utmärkt att leva utan.