I understand that everything in vb.net is a object. If that is the case, why is new keyword not used when creating a datatable object?
Dim dt as Datatable
dt.coloumns.add()
vs
Dim dt as Datatable = new Datatable
dt.coloumns.add()
Both seem to do the same things. However, in which scenario should I use new keyword? Are therere specific objects I don't need to use the new keyword? I understand that for common things like string, integer etc you don't need to instantiate the object. Is it the same case for DataTable too?
Dim dt as Datatable is merely declaration of the variable. It does not initialise it, so by default the value of dt is null (Nothing in VB I believe). Note that only declaring the value is not illegal at all, so you are perfectly within your rights to do so.
On the other hand, Dim dt as Datatable = new Datatable declares as well as initialises the variable. That is to say, new will initialise the declared variable with the appropriate value. If an class has a constructor which accepts parameters, then you can use new along with the constructor to create a new instance of that class and assign your chosen values to the class properties instead of using the default values.
The difference between your examples is that dt.Columns.add() will throw an error in the first example, since you are trying to call a method on a null object. In the second case, you have used new to provide an initial value to the variable. As a result, you can access the Columns property of a non-null object without any issue.
Now let's come to your other point - "I understand that for common things like string, integer etc you don't need to instantiate the object. Is it the same case for DataTable too?" Things like Integer are primitive datatypes, and so they have default non-null values. If you don't explicitly initialise with a value, they will take the default values. e.g. Dim x As Integer will automatically make x equal to 0
For objects, the default value is null, so it will cause problems if you try to do anything with that object without assigning a non-null value to it first. There are 2 ways to assign the non-null value:
Use new to initialise it.
Directly assign a value which is the result of some other processing in your code.
Related
I have a question about declaring a datatable variable.
Is there any difference if I declared a datatable variable as:
Dim xDt as new datatable
or
Dim xDt as new datatable()
??
Firstly, you're not declaring a class there. You are declaring a variable of type DataTable. The declaration is irrelevant anyway. What matters is that you are creating an instance of the DataTable class by invoking a constructor with the New keyword. A constructor is just a special method and, in VB, you can omit the parentheses when calling a method without arguments. This:
Dim table As New DataTable
is functionally equivalent to this:
Dim table As DataTable = New DataTable
which is functionally equivalent to this:
Dim table As DataTable
table = New DataTable
As you can see there, the last line is what matters and the variable declaration is irrelevant. That last line is equivalent to this:
table = New DataTable()
Whether you include the parentheses or not is up to you but I would suggest that you pick an option for a logical reason and stick to it consistently.
Personally, I always include parentheses on standard method calls but I always omit them from constructors. I do the former to make methods easily distinguishable from properties, so I would do this:
Dim str = obj.ToString()
rather than this:
Dim str = obj.ToString
With constructors though, there's little risk of mistaking them for properties but there is some risk of mistaking them for arrays, e.g.
Dim tables As DataTable()
Declares a variable of type DataTable array without creating an object while this:
Dim table As New DataTable()
declares a variable of type DataTable and assigns a new object to it. In my opinion, omitting the parentheses on constructors reduces the likelihood of confusion while including it on other methods does the same.
This question already has answers here:
Argument passed ByVal to VB.NET Function and manipulated there
(2 answers)
Closed 4 years ago.
The list value changeed here when passed ByVal why
,it must be not changed.
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim value As Integer = 1
Dim value2 As New List(Of Decimal)
value2.Add(1)
value2.Add(2)
' The integer value doesn't change here when passed ByVal.
Example1(value)
Console.WriteLine(value)
' The list value changeed here when passed ByVal.
Example3(value2)
Console.WriteLine(value)
End Sub
Sub Example1(ByVal test As Integer)
test = 10
End Sub
Sub Example3(ByVal test As List(Of Decimal))
test.Add(3)
End Sub
its solved ,the solution is making new copy:
Sub Example3(ByVal test As List(Of Decimal))
Dim testnew As New List(Of Decimal)
testnew.AddRange(test)
testnew.Add(3)
End Sub
You need to do some reading on value types and reference types and passing method arguments by value and by reference. They are related but not the same thing. When you pass a method argument by value, you create a copy of the variable being passed. If the variable is a value type, i.e. a structure, then that means creating a copy of the value. If the variable is a reference type, i.e. a class, then that means creating a copy of the reference. The thing is, the original reference and the copy still both refer to the same object.
The reason that reference types exist is that you wouldn't want to create copies of large objects every time you assigned them somewhere. In the case of passing a collection to a method, it's almost always the case that any change you make inside the method you will want to be reflected outside. In the rare case that you don't, it's up to you to create a copy of the collection first and pass that in.
When you pass a value type by value, you create a copy of the value. That means that no changes you make inside the method can affect the original variable. You can assign a new value to the parameter or you can set a property of the value and the change will not be reflected outside the method. Of course, value types should generally be immutable and so setting a property should not be possible, but there are times that that "rule" gets broken.
When you pass a reference type by value, you create a copy of the reference. That means that assigning a different object to the parameter inside the method will not affect the original variable. There is still only one object though, referred to by the original variable and the parameter. As such, if you set a property of that object via the parameter then that change will be reflected in the original variable, because it's the same object.
When you pass a value type by reference, you create a new reference to the value. That means that any changes you make inside the method will affect the original variable. You can assign a new value to the parameter or you can set a property of the value and the change will be reflected outside the method.
When you pass a reference type by reference, you create a new reference to the original reference. That means that assigning a different object to the parameter inside the method will affect the original variable. There's still just one object, so setting a property on the parameter will still affect the original variable too.
Those are the only four possibilities: value type by value, reference type by value, value type by reference and reference type by reference. In none of those scenarios is a copy of a reference type object made so in none of those scenarios can you set a property of a reference type object via a method parameter and have that change not be reflected in the original variable.
If you want a copy of the original object then it's up to you to create one explicitly. Whether you do that inside the method or outside really depends on the specific circumstances. That means that you need to change your code to this:
Sub Example3(ByVal test As List(Of Decimal))
Dim copy = test.ToList()
copy.Add(3)
End Sub
or this:
Dim copy = value2.ToList()
Example3(copy)
Let me just repeat the important point here: there is NO WAY to pass a reference type object to a method, modify the object via the parameter inside the method and have that not affect the original variable (assigning a different object to the parameter is NOT modifying the object). If you want a modification inside the method to not affect the original variable then you need a copy of the object and the ONLY way that will happen is if YOU do it explicitly.
In declaration of variables and objects, when exactly should I use "New" word, and when shouldn't I use it?
I know that I should declare a string without "New" word:
Dim mystring As String
I also know I should use it declaring a datatable:
Dim mytable As New Datatable()
New creates an object that is an instance of the specified class. If you just write the following then you have a reference, but the reference is Nothing as you didn't actually create a Datatable for it to refer to:
Dim mytable As Datatable
You don't typically use New for value types (Numbers, Dates, Booleans, Structures, Enums - a full list is here), as they always have a value (cannot be Nothing). For example this outputs 0:
Dim num as Int32
Console.WriteLine(num)
I wouldn't worry too much about this, but some value types (structures) can be initialised with New, which is somewhat inconsistent, for example:
Dim dec = New Decimal(2, 3, 4, True, 5)
this code is the same as others it is a random between 1 and 4 yet for some reason it says it is being used before it has a value it is the same code as 3 others that are the same but with different names yet this is happening can someone please help me?
Dim npc As Random
Dim ndamage As Integer
ndamage = npc.Next(1, 4)
If (Playerhealth.Value - ndamage) <= 0 Then
Playerhealth.Value = 0
Else
Playerhealth.Value = Playerhealth.Value - ndamage
End If
In the first three lines of code,
Dim npc As Random
Dim ndamage As Integer
ndamage = npc.Next(1, 4)
you declare npc and use it before it is assigned a value. You should use New to create a new instance:
Dim npc As New Random
Further Explanation
Random is a class, which means that its default value is Nothing (also called null in C#), so before it can be used it needs to be assigned a value. The easiest way in this case is to use New directly in the variable declaration line.
Random is a Class which provides a lot of methods to get different random numbers.
To access these methods you have to create an object (sometimes called instance) of that class.
This is done by the new operator. This operator will allocate new space on the heap (which is a memory area) and will fill it with objects values and references to methods and other objects.
If you skip the new statement, you program tries to access to not allocated memory. In several languages this will end up in an nullpointer exception, in vb.net you get an used before it has assigned value exception.
To solve your problem, create an object of the random class:
Dim npc As New Random
Basically, I have a function that has an optional dictionary argument. Since it's optional, it needs a default value, and I'd like to set it to an empty dictionary instead of Nothing. How do I go about that?
In Java, I would simply do this:
Collections.<K,V>emptyMap()
How do I do the equivalent in VB.NET?
(I'm using .NET 3.5).
There isn't a pre-canned empty dictionary in .NET. To create an empty dictionary, just go New Dictionary().
However, I believe you will not be allowed to use this the default value of an optional argument, because it can't be calculated at compile time and put into the DefaultValueAttribute. Instead you will need to overload the function: have one overload that takes the dictionary argument, and one that does not. The latter would just new up an empty dictionary as above, and call the first overload.
There is no way to specify an empty Dictionary as the default value for a parameter in VB.Net. VB.Net only supports values that can be encoded in MetaData and creating a new instance of a Dictionary is not one of them.
One option you do have though is to have an optional value which defaults to Nothing. In the case of Nothing create an empty dictionary. For instance.
Public Sub SomeMethod(Optional ByVal map as Dictionary(Of Key,Value) = Nothing)
if map Is Nothing Then
map = new Dictionary(Of Key,Value)
ENd If
...
End Sub
Depending on the purpose, it might be somewhat more resource-saving (i.e. in terms of memory) if the meant-to-be empty Dictionary is created with a Capacity of 0:
var empty = new Dictionary<string, string>(0);