Reputation: 13
I'm a newb to VB.NET and I'm having trouble with understanding how the Return actually works in a Function. The terminology I use will probably be incorrect but hopefully you'll understand what I'm driving toward.
I have a public module with a public function which opens an oledb connection to a csv file and gets the data. The function 'Return' csvDataSet. From my main form I can dim a new dataset (ds) and do the following:
Dim ds As New DataSet
DataGridView1.DataSource = FillDataSet(ds).Tables(0).DefaultView
DataGridView1 populates and all is well.
However, I've read that if I use a Class instead of a Module and use a Public Shared Function to return csvDataSet, it should be Static and I wouldn't need a new instance (in this case ds). I can't seem to make that work, so I know I'm missing something stupid in my understanding. If csvDataSet is Returned from a Public Shared Function inside a Public Class, should I always be able to set something to that csvDataSet i.e.
DataGridView1.DataSource = csvDataSet.Tables(0).DefaultView 'or something similar?
I know it's not a big deal to do it the way I'm doing it and Dim ds as New DataSet
and get it that way. I just want to understand why I can't just use csvDataSet if it already contains all the pertinent data. Hopefully that was a tad clearer than mud!
Adding Code as requested. Module:
Imports System.Data.OleDb
Imports System.IO
Module modGetData
'Public strLastFirst As String
Public Function FillDataSet(ByVal csvDataSet As DataSet) As DataSet
Dim fi As New FileInfo("c:\prospects.csv")
Dim connectionString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=Text;Data Source=" & fi.DirectoryName
Dim conn As New OleDbConnection(connectionString)
Dim cmdSelect As New OleDbCommand("SELECT * FROM " & fi.Name, conn)
Dim adapter1 As New OleDbDataAdapter
conn.Open()
adapter1.SelectCommand = cmdSelect
adapter1.Fill(csvDataSet, "DATA")
Return csvDataSet
conn.Close()
End Function
End Module
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ds As New DataSet
DataGridView1.DataSource = FillDataSet(ds).Tables(0).DefaultView
Upvotes: 1
Views: 2414
Reputation: 13571
First, if someone mentioned Static, then they are most likely a C# developer and really meant Shared. Static is a keyword that both C# and VB have, but the concepts are totally different. The C# static keyword corresponds to the VB keyword Shared. The VB keyword Static refers to a concept that C# simply doesn’t have. By which I mean that it’s impossible to write equivalent code in C#, although you can write code that is functionally equivalent.
Secondly, the FillDatSet as written can NOT be made Shared as it is in a Module, and methods in a Module cannot be shared. If it was in a class, it could be made Shared because it doesn’t use anything outside of the function. As written, it could be turned into a Sub, as there is no reason it needs to return csvDataSet. You pass in a dataset, modify it, and then return the modified dataset. What you need to realize, is that even though you modified it, it is the same dataset. In this case you might think of it as a bucket that is passed in empty and then returned full. But it’s the same bucket that you created before passing it to the FillDataSet function.
if I was doing a code review, I would suggest that you leave it a function, rename it to GetProspectsDS, move the csvDataSet As DataSet
into the body of the function as Dim csvDataSet As New DataSet
. There’s no reason why you need to pass in an empty bucket when it’s just as easy to create a new bucket. You would then use it as GetProspectsDS.Tables(0).DefaultView
Upvotes: 0
Reputation: 416131
There is some terminology we need to be clear up:
The [FillDataSet()] function 'Return' csvDataSet.
This is minor, but Return
implies something more like this:
Dim ds As DataSet = FillDataSet()
DataGridView1.DataSource = ds.Tables(0).DefaultView
or even:
DataGridView1.DataSource = FillDataSet().Tables(0).DefaultView
Notice we declare DataSet
, but we did not use New
. We let the variable be populated when the function returned. And because of that, we did not need to pass it to the function.
if I use ... a Public Shared Function to return csvDataSet, it [would] be Static
Static
is word used often in other languages, but it means something completely different in VB.Net. When those other languages say static
, you should hear it at Shared
. VB.Net's Static
is a different concept that does not have an equivalent in most of other languages. Using it here makes things more confusing.
I wouldn't need a new instance (in this case ds)
You still need an instance, but you would not need to create that instance locally. You can let the method create it's own instance. You can do this with a Module
, too. You don't gain anything special by having a Class
with a Shared
method.
The important thing to understand here is the difference between a variable, an object, and a reference.
In the first code sample in the question, ds
is a variable. It's a name you can use in code with a specific scope. However, this does not imply any actual memory!
Using the New
keyword as part of the declaration also creates an object. The object is the actual value in memory, but this is completely separate from the ds
variable.
Finally, because the ds
variable is declared in the same line with the New
keyword, the variable is also initialized to refer to the memory that was allocated for the DataSet object. But you can have a variable with no reference (it's Nothing
). And you can have an object with many references (or none... and then the object becomes eligible for disposal). You can change with object a variable refers to.
Knowing which you mean: object, reference, or variable, as well as how they are passed and returned between functions, is extremely important to writing good and effective code.
For this question, you can create an object with New
in a method, and return the result so a reference is assigned to a variable where the method was called. You would want to change the FillDataSet()
method like this:
Public Function FillDataSet() As DataSet
Dim ds As New DataSet
' Rest of the method is here
Return ds
End Function
Then you would be able to call the method as I demonstrated earlier.
The reason to do this, is the less a function needs to depend on outside variables (what we call "shared state"), the easier they are to write, debug, change, and maintain.
With that in mind, you want to think about changing the FillDataSet()
method even more:
Public Function FillDataSet(SQL As String, Params parameters() As OleDbParameter) As DataSet
Dim ds As New DataSet
' Rest of the method is here
Return ds
End Function
Take special note of the second function argument. It is there to avoid SQL Injection problems. It's hard to over-state how important that is.
Upvotes: 0