2

I think I'm missing something fundamental about how DataTables work. The following procedure starts with GetData, bringing in what as a filled DataTable. All the following code does is pass through copies of the datatable, manipulate it, then return it:

Sub GetData(ByVal what As DataTable)
    Dim Part As DataTable = Generate(what)
End Sub


Function Generate(ByVal brown As DataTable)
    Dim lameface As DataTable = DoStuff(brown)

    Return lameface
End Function


Function DoStuff(ByVal cow As DataTable)
    Dim result As DataTable = cow

    result.Rows.RemoveAt(0)

    Return result
End Function

The way this is written above, function DoStuff will remove the top row from result and cow. Similarly, brown and what will also have that first row removed, even though they are sent as ByVal.

If I change the first line in DoStuff from

Dim result As DataTable = cow

to

Dim result As DataTable = cow.copy

then cow, brown and what are left alone. Why is this? Marking a parameter as ByVal is supposed to send a copy of the object instead of the original, so why do I have tell it to use a copy when instantiating result? If I do a similar procedure using integers instead of datatables, it works as I would expect. What am I missing about datatables?

I poked around on MSDN's articles for datatables and didn't see anything that spoke to this. Thanks for your help!

Jon
  • 1,189
  • 11
  • 17
  • `DataTable` is a reference type, therefore you don't have copies of the table but just of it's reference. So if you modify it you will modify the original table. – Tim Schmelter Dec 13 '13 at 14:18
  • http://msdn.microsoft.com/en-us/library/8b0bdca4.aspx (applies to VB.NET as well) – nmclean Dec 13 '13 at 14:23

1 Answers1

5

The ByVal keyword doesn't necessarily indicate that a copy of the value is passed to the method. If the parameter is a reference type, like a DataTable, then a copy of the pointer is passed to the method - it still references the same object, so any changes made to the object in the method will be maintained once the method completes execution.

The ByRef keyword would permit the method to change the object the variable is pointing to, or the actual value if the parameter is a simple type (like int).

In your situation above, if you want to remove a row inside DoStuff, but not affect the source DataTable, then you need to make a copy of the DataTable before doing the remove operation.

davisoa
  • 5,407
  • 1
  • 28
  • 34
  • That makes sense. However, the MSDN article on Value & Reference Types (http://msdn.microsoft.com/en-us/library/t63sy5hs(v=vs.90).aspx) says strings are reference types. When I try this procedure using a string (instead of a datatable), it works the same way an integer does. Why is that? – Jon Dec 13 '13 at 14:32
  • Apparently strings are a special case. http://stackoverflow.com/questions/17876309/reference-types-behaves-like-value-type-in-vb-net – Jon Dec 13 '13 at 14:38
  • For any future viewers, this post was also helpful: http://stackoverflow.com/questions/19707622/byval-and-byref-with-reference-type – Jon Dec 13 '13 at 16:30